#include "DataTranSrv.h"

#include <QtSql>

#include "ComStruct.h"
#include "rtdb.h"
#include "ModbusFactory.h"
#include "AppDefine.h"
#include "LogFile.h"
#include "TcpClient.h"
#include "ModbusAddress.h"

CDataTranSrv::CDataTranSrv(QObject *parent, CModbusFactory* pModbusFactory)
	: QThread(parent)
    , m_pModbusFactory(pModbusFactory)
{
    Init();
}

void CDataTranSrv::Init()
{
    InitMembers();
    InitTcpClients();
    InitConnect();
}

void CDataTranSrv::InitMembers()
{
    m_pRTDB = 0;
    m_pBattStack = 0;

    m_iOrgLang = 0;

    m_usPort = 502;
    m_iIdleTime = 10; //默认10秒
    m_uaModbusAddrOffset = 0;

    m_lstSql.clear();
    for (int i = 0; i < MAX_BANK_NUM; ++i)
    {
        m_pAlmCacheSem[i] = 0;
    }

    m_dtLastChgDropPower = QDateTime::currentDateTime().addSecs(-30); //上次充电降功率时间
    m_dtLastDhgDropPower = m_dtLastChgDropPower; //上次放电降功率时间
    m_iCheckEMSLinkCount = 0;
}

void CDataTranSrv::InitTcpClients()
{
    m_pTcpServer = new QTcpServer(this);
    m_pTcpServer->setMaxPendingConnections(MAX_MODBUS_TCP_CLIENT_NUM);
    m_plstTcpClient = new QList<STcpClient*>;

    STcpClient* pTcpClient = 0;
    for (int i = 0; i < MAX_MODBUS_TCP_CLIENT_NUM; ++i)
    {
        pTcpClient = new STcpClient;

        pTcpClient->pTcpSocket = 0;
        pTcpClient->pMutexClient = new QMutex;

        pTcpClient->pDataBuf = new char[SNED_BUFFER_LENGHT];
        pTcpClient->iIdleTimeCount = 0;

        pTcpClient->strTcpClient = "";

        m_plstTcpClient->append(pTcpClient);
    }
}

void CDataTranSrv::InitConnect()
{
    QObject::connect(m_pTcpServer, SIGNAL(newConnection()), this, SLOT(newTcpConn()));
    QObject::connect(this, SIGNAL(tcpCliDisconnectedSgl(int)), this, SLOT(tcpCliDisconnectedSlot(int)));
    QObject::connect(this, SIGNAL(switchLang()), parent(), SLOT(switchLang()));
}

CDataTranSrv::~CDataTranSrv()
{
	if (m_pTcpServer)
	{
		delete m_pTcpServer;
		m_pTcpServer = 0;
	}

	if (m_plstTcpClient)
	{
		while (!m_plstTcpClient->isEmpty())
		{
			STcpClient* pTcpClient = m_plstTcpClient->takeFirst();
			if (pTcpClient)
			{
				if (pTcpClient->pMutexClient)
				{
					delete pTcpClient->pMutexClient;
					pTcpClient->pMutexClient = 0;
				}

				if (pTcpClient->pDataBuf)
				{
					delete []pTcpClient->pDataBuf;
					pTcpClient->pDataBuf = 0;
				}

				delete pTcpClient;
			}
		}

		delete m_plstTcpClient;
		m_plstTcpClient = 0;
	}
}

void CDataTranSrv::setRTDB(CRTDB* pRTDB, CBattStack* pBattStack)
{
	m_pRTDB = pRTDB;
	m_pBattStack = pBattStack;
}

void CDataTranSrv::startDataTranSrv()
{
    if (m_pTcpServer->listen(QHostAddress::Any, m_usPort))
    {
        KG_LOG_INFO(QString("在%1端口开启tcp监听时成功").arg(m_usPort));
    }
    else
    {
        KG_LOG_INFO(QString("在%1端口开启tcp监听时失败").arg(m_usPort));
    }
}

void CDataTranSrv::initTcpClientSlots(int iCliIndex)
{
	STcpClient* pTcpClient = m_plstTcpClient->at(iCliIndex);

	if (pTcpClient && pTcpClient->pTcpSocket)
	{
		if (0 == iCliIndex)
		{
			QObject::connect(pTcpClient->pTcpSocket, SIGNAL(disconnected()), this, SLOT(tcpCli1Disconnected()));
			QObject::connect(pTcpClient->pTcpSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(tcpCli1Error(QAbstractSocket::SocketError)));
			QObject::connect(pTcpClient->pTcpSocket, SIGNAL(readyRead()), this, SLOT(tcpCli1ReadDatagram()));
		}
		else if (1 == iCliIndex)
		{
			QObject::connect(pTcpClient->pTcpSocket, SIGNAL(disconnected()), this, SLOT(tcpCli2Disconnected()));
			QObject::connect(pTcpClient->pTcpSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(tcpCli2Error(QAbstractSocket::SocketError)));
			QObject::connect(pTcpClient->pTcpSocket, SIGNAL(readyRead()), this, SLOT(tcpCli2ReadDatagram()));
		}
		else if (2 == iCliIndex)
		{
			QObject::connect(pTcpClient->pTcpSocket, SIGNAL(disconnected()), this, SLOT(tcpCli13Disconnected()));
			QObject::connect(pTcpClient->pTcpSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(tcpCli3Error(QAbstractSocket::SocketError)));
			QObject::connect(pTcpClient->pTcpSocket, SIGNAL(readyRead()), this, SLOT(tcpCli3ReadDatagram()));
		}
		else if (3 == iCliIndex)
		{
			QObject::connect(pTcpClient->pTcpSocket, SIGNAL(disconnected()), this, SLOT(tcpCli4Disconnected()));
			QObject::connect(pTcpClient->pTcpSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(tcpCli4Error(QAbstractSocket::SocketError)));
			QObject::connect(pTcpClient->pTcpSocket, SIGNAL(readyRead()), this, SLOT(tcpCli4ReadDatagram()));
		}
		else if (4 == iCliIndex)
		{
			QObject::connect(pTcpClient->pTcpSocket, SIGNAL(disconnected()), this, SLOT(tcpCli5Disconnected()));
			QObject::connect(pTcpClient->pTcpSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(tcpCli5Error(QAbstractSocket::SocketError)));
			QObject::connect(pTcpClient->pTcpSocket, SIGNAL(readyRead()), this, SLOT(tcpCli5ReadDatagram()));
		}
		else if (5 == iCliIndex)
		{
			QObject::connect(pTcpClient->pTcpSocket, SIGNAL(disconnected()), this, SLOT(tcpCli6Disconnected()));
			QObject::connect(pTcpClient->pTcpSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(tcpCli6Error(QAbstractSocket::SocketError)));
			QObject::connect(pTcpClient->pTcpSocket, SIGNAL(readyRead()), this, SLOT(tcpCli6ReadDatagram()));
		}
		else if (6 == iCliIndex)
		{
			QObject::connect(pTcpClient->pTcpSocket, SIGNAL(disconnected()), this, SLOT(tcpCli7Disconnected()));
			QObject::connect(pTcpClient->pTcpSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(tcpCli7Error(QAbstractSocket::SocketError)));
			QObject::connect(pTcpClient->pTcpSocket, SIGNAL(readyRead()), this, SLOT(tcpCli7ReadDatagram()));
		}
		else if (7 == iCliIndex)
		{
			QObject::connect(pTcpClient->pTcpSocket, SIGNAL(disconnected()), this, SLOT(tcpCli8Disconnected()));
			QObject::connect(pTcpClient->pTcpSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(tcpCli8Error(QAbstractSocket::SocketError)));
			QObject::connect(pTcpClient->pTcpSocket, SIGNAL(readyRead()), this, SLOT(tcpCli8ReadDatagram()));
		}
		else if (8 == iCliIndex)
		{
			QObject::connect(pTcpClient->pTcpSocket, SIGNAL(disconnected()), this, SLOT(tcpCli9Disconnected()));
			QObject::connect(pTcpClient->pTcpSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(tcpCli9Error(QAbstractSocket::SocketError)));
			QObject::connect(pTcpClient->pTcpSocket, SIGNAL(readyRead()), this, SLOT(tcpCli9ReadDatagram()));
		}
		else if (9 == iCliIndex)
		{
			QObject::connect(pTcpClient->pTcpSocket, SIGNAL(disconnected()), this, SLOT(tcpCli10Disconnected()));
			QObject::connect(pTcpClient->pTcpSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(tcpCli10Error(QAbstractSocket::SocketError)));
			QObject::connect(pTcpClient->pTcpSocket, SIGNAL(readyRead()), this, SLOT(tcpCli10ReadDatagram()));
		}
		else if (10 == iCliIndex)
		{
			QObject::connect(pTcpClient->pTcpSocket, SIGNAL(disconnected()), this, SLOT(tcpCli11Disconnected()));
			QObject::connect(pTcpClient->pTcpSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(tcpCli11Error(QAbstractSocket::SocketError)));
			QObject::connect(pTcpClient->pTcpSocket, SIGNAL(readyRead()), this, SLOT(tcpCli11ReadDatagram()));
		}
		else if (11 == iCliIndex)
		{
			QObject::connect(pTcpClient->pTcpSocket, SIGNAL(disconnected()), this, SLOT(tcpCli12Disconnected()));
			QObject::connect(pTcpClient->pTcpSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(tcpCli12Error(QAbstractSocket::SocketError)));
			QObject::connect(pTcpClient->pTcpSocket, SIGNAL(readyRead()), this, SLOT(tcpCli12ReadDatagram()));
		}
		else if (12 == iCliIndex)
		{
			QObject::connect(pTcpClient->pTcpSocket, SIGNAL(disconnected()), this, SLOT(tcpCli13Disconnected()));
			QObject::connect(pTcpClient->pTcpSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(tcpCli13Error(QAbstractSocket::SocketError)));
			QObject::connect(pTcpClient->pTcpSocket, SIGNAL(readyRead()), this, SLOT(tcpCli13ReadDatagram()));
		}
		else if (13 == iCliIndex)
		{
			QObject::connect(pTcpClient->pTcpSocket, SIGNAL(disconnected()), this, SLOT(tcpCli14Disconnected()));
			QObject::connect(pTcpClient->pTcpSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(tcpCli14Error(QAbstractSocket::SocketError)));
			QObject::connect(pTcpClient->pTcpSocket, SIGNAL(readyRead()), this, SLOT(tcpCli14ReadDatagram()));
		}
		else if (14 == iCliIndex)
		{
			QObject::connect(pTcpClient->pTcpSocket, SIGNAL(disconnected()), this, SLOT(tcpCli15Disconnected()));
			QObject::connect(pTcpClient->pTcpSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(tcpCli15Error(QAbstractSocket::SocketError)));
			QObject::connect(pTcpClient->pTcpSocket, SIGNAL(readyRead()), this, SLOT(tcpCli15ReadDatagram()));
		}
		else if (15 == iCliIndex)
		{
			QObject::connect(pTcpClient->pTcpSocket, SIGNAL(disconnected()), this, SLOT(tcpCli16Disconnected()));
			QObject::connect(pTcpClient->pTcpSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(tcpCli16Error(QAbstractSocket::SocketError)));
			QObject::connect(pTcpClient->pTcpSocket, SIGNAL(readyRead()), this, SLOT(tcpCli16ReadDatagram()));
		}
		else if (16 == iCliIndex)
		{
			QObject::connect(pTcpClient->pTcpSocket, SIGNAL(disconnected()), this, SLOT(tcpCli17Disconnected()));
			QObject::connect(pTcpClient->pTcpSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(tcpCli17Error(QAbstractSocket::SocketError)));
			QObject::connect(pTcpClient->pTcpSocket, SIGNAL(readyRead()), this, SLOT(tcpCli17ReadDatagram()));
		}
	}
}

void CDataTranSrv::newTcpConn()
{
	bool bFind = false;
	STcpClient* pTcpClient = 0;
	for (int i = 0; i < MAX_MODBUS_TCP_CLIENT_NUM; ++i)
	{
		pTcpClient = m_plstTcpClient->at(i);
		
		if (pTcpClient)
		{
            if (0 == pTcpClient->pTcpSocket) //空闲
			{
				pTcpClient->pTcpSocket = m_pTcpServer->nextPendingConnection();

				if (pTcpClient->pTcpSocket)
				{
					initTcpClientSlots(i);
					
					pTcpClient->iIdleTimeCount = 0;
					pTcpClient->strTcpClient = pTcpClient->pTcpSocket->peerAddress().toString();
                    KG_LOG_INFO(QString("接收到新的tcp客户端连接请求(%1)").arg(pTcpClient->strTcpClient));

					bFind = true;
				}
			}
		}

	}

    if (!bFind) //Not find
	{
        //超过最大ModbusTCP连接数，我们主动关闭客户端的TcpSocket连接
		QTcpSocket* pTcpClient = m_pTcpServer->nextPendingConnection();

		if (pTcpClient)
		{
			pTcpClient->disconnectFromHost();
			if (QAbstractSocket ::ConnectedState == pTcpClient->state())
			{
				pTcpClient->waitForDisconnected();
			}

            KG_LOG_INFO(QString("拒绝新的客户端tcp请求(%1)").arg(pTcpClient->peerAddress().toString()));

			delete pTcpClient;
			pTcpClient = 0;
		}
	}
}

void CDataTranSrv::tcpCli1Disconnected ()
{
	STcpClient* pTcpClient = m_plstTcpClient->at(0);
	if (pTcpClient)
	{
		pTcpClient->pMutexClient->lock();

		if (pTcpClient->pTcpSocket)
		{
			QObject::disconnect(pTcpClient->pTcpSocket, SIGNAL(disconnected()), this, SLOT(tcpCli1Disconnected()));
			QObject::disconnect(pTcpClient->pTcpSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(tcpCli1Error(QAbstractSocket::SocketError)));
			QObject::disconnect(pTcpClient->pTcpSocket, SIGNAL(readyRead()), this, SLOT(tcpCli1ReadDatagram()));

			pTcpClient->pTcpSocket->disconnectFromHost();
			if (QAbstractSocket ::ConnectedState == pTcpClient->pTcpSocket->state())
			{
				pTcpClient->pTcpSocket->waitForDisconnected();
			}

            KG_LOG_INFO(QString("tcp客户端1主动断开连接(%1)").arg(pTcpClient->strTcpClient));

			pTcpClient->pTcpSocket = 0;
			pTcpClient->strTcpClient = "";
			pTcpClient->iIdleTimeCount  = 0;
		}

		pTcpClient->pMutexClient->unlock();
	}
}

void CDataTranSrv::tcpCli2Disconnected ()
{
	STcpClient* pTcpClient = m_plstTcpClient->at(1);
	if (pTcpClient)
	{
		pTcpClient->pMutexClient->lock();

		if (pTcpClient->pTcpSocket)
		{
			QObject::disconnect(pTcpClient->pTcpSocket, SIGNAL(disconnected()), this, SLOT(tcpCli2Disconnected()));
			QObject::disconnect(pTcpClient->pTcpSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(tcpCli2Error(QAbstractSocket::SocketError)));
			QObject::disconnect(pTcpClient->pTcpSocket, SIGNAL(readyRead()), this, SLOT(tcpCli2ReadDatagram()));

			pTcpClient->pTcpSocket->disconnectFromHost();
			if (QAbstractSocket ::ConnectedState == pTcpClient->pTcpSocket->state())
			{
				pTcpClient->pTcpSocket->waitForDisconnected();
			}

            KG_LOG_INFO(QString("tcp客户端2主动断开连接(%1)").arg(pTcpClient->strTcpClient));

			pTcpClient->pTcpSocket = 0;
			pTcpClient->strTcpClient = "";
			pTcpClient->iIdleTimeCount  = 0;
		}

		pTcpClient->pMutexClient->unlock();
	}
}

void CDataTranSrv::tcpCli3Disconnected ()
{
	STcpClient* pTcpClient = m_plstTcpClient->at(2);
	if (pTcpClient)
	{
		pTcpClient->pMutexClient->lock();

		if (pTcpClient->pTcpSocket)
		{
			QObject::disconnect(pTcpClient->pTcpSocket, SIGNAL(disconnected()), this, SLOT(tcpCli3Disconnected()));
			QObject::disconnect(pTcpClient->pTcpSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(tcpCli3Error(QAbstractSocket::SocketError)));
			QObject::disconnect(pTcpClient->pTcpSocket, SIGNAL(readyRead()), this, SLOT(tcpCli3ReadDatagram()));

			pTcpClient->pTcpSocket->disconnectFromHost();
			if (QAbstractSocket ::ConnectedState == pTcpClient->pTcpSocket->state())
			{
				pTcpClient->pTcpSocket->waitForDisconnected();
			}

            KG_LOG_INFO(QString("tcp客户端3主动断开连接(%1)").arg(pTcpClient->strTcpClient));

			pTcpClient->pTcpSocket = 0;
			pTcpClient->strTcpClient = "";
			pTcpClient->iIdleTimeCount  = 0;
		}

		pTcpClient->pMutexClient->unlock();
	}
}

void CDataTranSrv::tcpCli4Disconnected ()
{
	STcpClient* pTcpClient = m_plstTcpClient->at(3);
	if (pTcpClient)
	{
		pTcpClient->pMutexClient->lock();

		if (pTcpClient->pTcpSocket)
		{
			QObject::disconnect(pTcpClient->pTcpSocket, SIGNAL(disconnected()), this, SLOT(tcpCli4Disconnected()));
			QObject::disconnect(pTcpClient->pTcpSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(tcpCli4Error(QAbstractSocket::SocketError)));
			QObject::disconnect(pTcpClient->pTcpSocket, SIGNAL(readyRead()), this, SLOT(tcpCli4ReadDatagram()));

			pTcpClient->pTcpSocket->disconnectFromHost();
			if (QAbstractSocket ::ConnectedState == pTcpClient->pTcpSocket->state())
			{
				pTcpClient->pTcpSocket->waitForDisconnected();
			}

            KG_LOG_INFO(QString("tcp客户端4主动断开连接(%1)").arg(pTcpClient->strTcpClient));

			pTcpClient->pTcpSocket = 0;
			pTcpClient->strTcpClient = "";
			pTcpClient->iIdleTimeCount  = 0;
		}

		pTcpClient->pMutexClient->unlock();
	}
}

void CDataTranSrv::tcpCli5Disconnected ()
{
	STcpClient* pTcpClient = m_plstTcpClient->at(4);
	if (pTcpClient)
	{
		pTcpClient->pMutexClient->lock();

		if (pTcpClient->pTcpSocket)
		{
			QObject::disconnect(pTcpClient->pTcpSocket, SIGNAL(disconnected()), this, SLOT(tcpCli5Disconnected()));
			QObject::disconnect(pTcpClient->pTcpSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(tcpCli5Error(QAbstractSocket::SocketError)));
			QObject::disconnect(pTcpClient->pTcpSocket, SIGNAL(readyRead()), this, SLOT(tcpCli5ReadDatagram()));

			pTcpClient->pTcpSocket->disconnectFromHost();
			if (QAbstractSocket ::ConnectedState == pTcpClient->pTcpSocket->state())
			{
				pTcpClient->pTcpSocket->waitForDisconnected();
			}

            KG_LOG_INFO(QString("tcp客户端5主动断开连接(%1)").arg(pTcpClient->strTcpClient));

			pTcpClient->pTcpSocket = 0;
			pTcpClient->strTcpClient = "";
			pTcpClient->iIdleTimeCount  = 0;
		}

		pTcpClient->pMutexClient->unlock();
	}
}

void CDataTranSrv::tcpCli6Disconnected ()
{
	STcpClient* pTcpClient = m_plstTcpClient->at(5);
	if (pTcpClient)
	{
		pTcpClient->pMutexClient->lock();

		if (pTcpClient->pTcpSocket)
		{
			QObject::disconnect(pTcpClient->pTcpSocket, SIGNAL(disconnected()), this, SLOT(tcpCli6Disconnected()));
			QObject::disconnect(pTcpClient->pTcpSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(tcpCli6Error(QAbstractSocket::SocketError)));
			QObject::disconnect(pTcpClient->pTcpSocket, SIGNAL(readyRead()), this, SLOT(tcpCli6ReadDatagram()));

			pTcpClient->pTcpSocket->disconnectFromHost();
			if (QAbstractSocket ::ConnectedState == pTcpClient->pTcpSocket->state())
			{
				pTcpClient->pTcpSocket->waitForDisconnected();
			}

            KG_LOG_INFO(QString("tcp客户端6主动断开连接(%1)").arg(pTcpClient->strTcpClient));

			pTcpClient->pTcpSocket = 0;
			pTcpClient->strTcpClient = "";
			pTcpClient->iIdleTimeCount  = 0;
		}

		pTcpClient->pMutexClient->unlock();
	}
}

void CDataTranSrv::tcpCli7Disconnected ()
{
	STcpClient* pTcpClient = m_plstTcpClient->at(6);
	if (pTcpClient)
	{
		pTcpClient->pMutexClient->lock();

		if (pTcpClient->pTcpSocket)
		{
			QObject::disconnect(pTcpClient->pTcpSocket, SIGNAL(disconnected()), this, SLOT(tcpCli7Disconnected()));
			QObject::disconnect(pTcpClient->pTcpSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(tcpCli7Error(QAbstractSocket::SocketError)));
			QObject::disconnect(pTcpClient->pTcpSocket, SIGNAL(readyRead()), this, SLOT(tcpCli7ReadDatagram()));

			pTcpClient->pTcpSocket->disconnectFromHost();
			if (QAbstractSocket ::ConnectedState == pTcpClient->pTcpSocket->state())
			{
				pTcpClient->pTcpSocket->waitForDisconnected();
			}

            KG_LOG_INFO(QString("tcp客户端7主动断开连接(%1)").arg(pTcpClient->strTcpClient));

			pTcpClient->pTcpSocket = 0;
			pTcpClient->strTcpClient = "";
			pTcpClient->iIdleTimeCount  = 0;
		}

		pTcpClient->pMutexClient->unlock();
	}
}

void CDataTranSrv::tcpCli8Disconnected ()
{
	STcpClient* pTcpClient = m_plstTcpClient->at(7);
	if (pTcpClient)
	{
		pTcpClient->pMutexClient->lock();

		if (pTcpClient->pTcpSocket)
		{
			QObject::disconnect(pTcpClient->pTcpSocket, SIGNAL(disconnected()), this, SLOT(tcpCli8Disconnected()));
			QObject::disconnect(pTcpClient->pTcpSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(tcpCli8Error(QAbstractSocket::SocketError)));
			QObject::disconnect(pTcpClient->pTcpSocket, SIGNAL(readyRead()), this, SLOT(tcpCli8ReadDatagram()));

			pTcpClient->pTcpSocket->disconnectFromHost();
			if (QAbstractSocket ::ConnectedState == pTcpClient->pTcpSocket->state())
			{
				pTcpClient->pTcpSocket->waitForDisconnected();
			}

            KG_LOG_INFO(QString("tcp客户端8主动断开连接(%1)").arg(pTcpClient->strTcpClient));

			pTcpClient->pTcpSocket = 0;
			pTcpClient->strTcpClient = "";
			pTcpClient->iIdleTimeCount  = 0;
		}

		pTcpClient->pMutexClient->unlock();
	}
}

void CDataTranSrv::tcpCli9Disconnected ()
{
	STcpClient* pTcpClient = m_plstTcpClient->at(8);
	if (pTcpClient)
	{
		pTcpClient->pMutexClient->lock();

		if (pTcpClient->pTcpSocket)
		{
			QObject::disconnect(pTcpClient->pTcpSocket, SIGNAL(disconnected()), this, SLOT(tcpCli9Disconnected()));
			QObject::disconnect(pTcpClient->pTcpSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(tcpCli9Error(QAbstractSocket::SocketError)));
			QObject::disconnect(pTcpClient->pTcpSocket, SIGNAL(readyRead()), this, SLOT(tcpCli9ReadDatagram()));

			pTcpClient->pTcpSocket->disconnectFromHost();
			if (QAbstractSocket ::ConnectedState == pTcpClient->pTcpSocket->state())
			{
				pTcpClient->pTcpSocket->waitForDisconnected();
			}

            KG_LOG_INFO(QString("tcp客户端9主动断开连接(%1)").arg(pTcpClient->strTcpClient));

			pTcpClient->pTcpSocket = 0;
			pTcpClient->strTcpClient = "";
			pTcpClient->iIdleTimeCount  = 0;
		}

		pTcpClient->pMutexClient->unlock();
	}
}

void CDataTranSrv::tcpCli10Disconnected ()
{
	STcpClient* pTcpClient = m_plstTcpClient->at(9);
	if (pTcpClient)
	{
		pTcpClient->pMutexClient->lock();

		if (pTcpClient->pTcpSocket)
		{
			QObject::disconnect(pTcpClient->pTcpSocket, SIGNAL(disconnected()), this, SLOT(tcpCli10Disconnected()));
			QObject::disconnect(pTcpClient->pTcpSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(tcpCli10Error(QAbstractSocket::SocketError)));
			QObject::disconnect(pTcpClient->pTcpSocket, SIGNAL(readyRead()), this, SLOT(tcpCli10ReadDatagram()));

			pTcpClient->pTcpSocket->disconnectFromHost();
			if (QAbstractSocket ::ConnectedState == pTcpClient->pTcpSocket->state())
			{
				pTcpClient->pTcpSocket->waitForDisconnected();
			}

            KG_LOG_INFO(QString("tcp客户端10主动断开连接(%1)").arg(pTcpClient->strTcpClient));

			pTcpClient->pTcpSocket = 0;
			pTcpClient->strTcpClient = "";
			pTcpClient->iIdleTimeCount  = 0;
		}

		pTcpClient->pMutexClient->unlock();
	}
}

void CDataTranSrv::tcpCli11Disconnected ()
{
	STcpClient* pTcpClient = m_plstTcpClient->at(10);
	if (pTcpClient)
	{
		pTcpClient->pMutexClient->lock();

		if (pTcpClient->pTcpSocket)
		{
			QObject::disconnect(pTcpClient->pTcpSocket, SIGNAL(disconnected()), this, SLOT(tcpCli11Disconnected()));
			QObject::disconnect(pTcpClient->pTcpSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(tcpCli11Error(QAbstractSocket::SocketError)));
			QObject::disconnect(pTcpClient->pTcpSocket, SIGNAL(readyRead()), this, SLOT(tcpCli11ReadDatagram()));

			pTcpClient->pTcpSocket->disconnectFromHost();
			if (QAbstractSocket ::ConnectedState == pTcpClient->pTcpSocket->state())
			{
				pTcpClient->pTcpSocket->waitForDisconnected();
			}

            KG_LOG_INFO(QString("tcp客户端11主动断开连接(%1)").arg(pTcpClient->strTcpClient));

			pTcpClient->pTcpSocket = 0;
			pTcpClient->strTcpClient = "";
			pTcpClient->iIdleTimeCount  = 0;
		}

		pTcpClient->pMutexClient->unlock();
	}
}

void CDataTranSrv::tcpCli12Disconnected ()
{
	STcpClient* pTcpClient = m_plstTcpClient->at(11);
	if (pTcpClient)
	{
		pTcpClient->pMutexClient->lock();

		if (pTcpClient->pTcpSocket)
		{
			QObject::disconnect(pTcpClient->pTcpSocket, SIGNAL(disconnected()), this, SLOT(tcpCli12Disconnected()));
			QObject::disconnect(pTcpClient->pTcpSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(tcpCli12Error(QAbstractSocket::SocketError)));
			QObject::disconnect(pTcpClient->pTcpSocket, SIGNAL(readyRead()), this, SLOT(tcpCli12ReadDatagram()));

			pTcpClient->pTcpSocket->disconnectFromHost();
			if (QAbstractSocket ::ConnectedState == pTcpClient->pTcpSocket->state())
			{
				pTcpClient->pTcpSocket->waitForDisconnected();
			}

            KG_LOG_INFO(QString("tcp客户端12主动断开连接(%1)").arg(pTcpClient->strTcpClient));

			pTcpClient->pTcpSocket = 0;
			pTcpClient->strTcpClient = "";
			pTcpClient->iIdleTimeCount  = 0;
		}

		pTcpClient->pMutexClient->unlock();
	}
}

void CDataTranSrv::tcpCli13Disconnected ()
{
	STcpClient* pTcpClient = m_plstTcpClient->at(12);
	if (pTcpClient)
	{
		pTcpClient->pMutexClient->lock();

		if (pTcpClient->pTcpSocket)
		{
			QObject::disconnect(pTcpClient->pTcpSocket, SIGNAL(disconnected()), this, SLOT(tcpCli13Disconnected()));
			QObject::disconnect(pTcpClient->pTcpSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(tcpCli13Error(QAbstractSocket::SocketError)));
			QObject::disconnect(pTcpClient->pTcpSocket, SIGNAL(readyRead()), this, SLOT(tcpCli13ReadDatagram()));

			pTcpClient->pTcpSocket->disconnectFromHost();
			if (QAbstractSocket ::ConnectedState == pTcpClient->pTcpSocket->state())
			{
				pTcpClient->pTcpSocket->waitForDisconnected();
			}

            KG_LOG_INFO(QString("tcp客户端13主动断开连接(%1)").arg(pTcpClient->strTcpClient));

			pTcpClient->pTcpSocket = 0;
			pTcpClient->strTcpClient = "";
			pTcpClient->iIdleTimeCount  = 0;
		}

		pTcpClient->pMutexClient->unlock();
	}
}

void CDataTranSrv::tcpCli14Disconnected ()
{
	STcpClient* pTcpClient = m_plstTcpClient->at(13);
	if (pTcpClient)
	{
		pTcpClient->pMutexClient->lock();

		if (pTcpClient->pTcpSocket)
		{
			QObject::disconnect(pTcpClient->pTcpSocket, SIGNAL(disconnected()), this, SLOT(tcpCli14Disconnected()));
			QObject::disconnect(pTcpClient->pTcpSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(tcpCli14Error(QAbstractSocket::SocketError)));
			QObject::disconnect(pTcpClient->pTcpSocket, SIGNAL(readyRead()), this, SLOT(tcpCli14ReadDatagram()));

			pTcpClient->pTcpSocket->disconnectFromHost();
			if (QAbstractSocket ::ConnectedState == pTcpClient->pTcpSocket->state())
			{
				pTcpClient->pTcpSocket->waitForDisconnected();
			}

            KG_LOG_INFO(QString("tcp客户端14主动断开连接(%1)").arg(pTcpClient->strTcpClient));

			pTcpClient->pTcpSocket = 0;
			pTcpClient->strTcpClient = "";
			pTcpClient->iIdleTimeCount  = 0;
		}

		pTcpClient->pMutexClient->unlock();
	}
}

void CDataTranSrv::tcpCli15Disconnected ()
{
	STcpClient* pTcpClient = m_plstTcpClient->at(14);
	if (pTcpClient)
	{
		pTcpClient->pMutexClient->lock();

		if (pTcpClient->pTcpSocket)
		{
			QObject::disconnect(pTcpClient->pTcpSocket, SIGNAL(disconnected()), this, SLOT(tcpCli15Disconnected()));
			QObject::disconnect(pTcpClient->pTcpSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(tcpCli15Error(QAbstractSocket::SocketError)));
			QObject::disconnect(pTcpClient->pTcpSocket, SIGNAL(readyRead()), this, SLOT(tcpCli15ReadDatagram()));

			pTcpClient->pTcpSocket->disconnectFromHost();
			if (QAbstractSocket ::ConnectedState == pTcpClient->pTcpSocket->state())
			{
				pTcpClient->pTcpSocket->waitForDisconnected();
			}

            KG_LOG_INFO(QString("tcp客户端15主动断开连接(%1)").arg(pTcpClient->strTcpClient));

			pTcpClient->pTcpSocket = 0;
			pTcpClient->strTcpClient = "";
			pTcpClient->iIdleTimeCount  = 0;
		}

		pTcpClient->pMutexClient->unlock();
	}
}

void CDataTranSrv::tcpCli16Disconnected ()
{
	STcpClient* pTcpClient = m_plstTcpClient->at(15);
	if (pTcpClient)
	{
		pTcpClient->pMutexClient->lock();

		if (pTcpClient->pTcpSocket)
		{
			QObject::disconnect(pTcpClient->pTcpSocket, SIGNAL(disconnected()), this, SLOT(tcpCli16Disconnected()));
			QObject::disconnect(pTcpClient->pTcpSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(tcpCli16Error(QAbstractSocket::SocketError)));
			QObject::disconnect(pTcpClient->pTcpSocket, SIGNAL(readyRead()), this, SLOT(tcpCli16ReadDatagram()));

			pTcpClient->pTcpSocket->disconnectFromHost();
			if (QAbstractSocket ::ConnectedState == pTcpClient->pTcpSocket->state())
			{
				pTcpClient->pTcpSocket->waitForDisconnected();
			}

            KG_LOG_INFO(QString("tcp客户端16主动断开连接(%1)").arg(pTcpClient->strTcpClient));

			pTcpClient->pTcpSocket = 0;
			pTcpClient->strTcpClient = "";
			pTcpClient->iIdleTimeCount  = 0;
		}

		pTcpClient->pMutexClient->unlock();
	}
}

void CDataTranSrv::tcpCli17Disconnected ()
{
	STcpClient* pTcpClient = m_plstTcpClient->at(16);
	if (pTcpClient)
	{
		pTcpClient->pMutexClient->lock();

		if (pTcpClient->pTcpSocket)
		{
			QObject::disconnect(pTcpClient->pTcpSocket, SIGNAL(disconnected()), this, SLOT(tcpCli17Disconnected()));
			QObject::disconnect(pTcpClient->pTcpSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(tcpCli17Error(QAbstractSocket::SocketError)));
			QObject::disconnect(pTcpClient->pTcpSocket, SIGNAL(readyRead()), this, SLOT(tcpCli17ReadDatagram()));

			pTcpClient->pTcpSocket->disconnectFromHost();
			if (QAbstractSocket ::ConnectedState == pTcpClient->pTcpSocket->state())
			{
				pTcpClient->pTcpSocket->waitForDisconnected();
			}

            KG_LOG_INFO(QString("tcp客户端17主动断开连接(%1)").arg(pTcpClient->strTcpClient));

			pTcpClient->pTcpSocket = 0;
			pTcpClient->strTcpClient = "";
			pTcpClient->iIdleTimeCount  = 0;
		}

		pTcpClient->pMutexClient->unlock();
	}
}

void CDataTranSrv::TcpClientError(QAbstractSocket::SocketError socketError, STcpClient* pTcpClient)
{
    if (0 == pTcpClient)
    {
        return;
    }
    if (0 == pTcpClient->pTcpSocket)
    {
        return;
    }

    switch (socketError)
    {
    case QAbstractSocket::RemoteHostClosedError:
        KG_LOG_INFO(QString("对方的tcp连接(%1)已关闭.").arg(pTcpClient->strTcpClient));
        break;
    case QAbstractSocket::HostNotFoundError:
        KG_LOG_INFO(QString("对方的tcp连接(%1)主机未找到.").arg(pTcpClient->strTcpClient));
        break;
    case QAbstractSocket::ConnectionRefusedError:
        KG_LOG_INFO(QString("对方的tcp连接(%1)已拒绝.").arg(pTcpClient->strTcpClient));
        break;
    default:
        KG_LOG_INFO(QString("对方的tcp连接(%1)发生了错误.").arg(pTcpClient->strTcpClient));
    }
}

void CDataTranSrv::tcpCli1Error(QAbstractSocket::SocketError socketError)
{
	STcpClient* pTcpClient = m_plstTcpClient->at(0);
    TcpClientError(socketError, pTcpClient);
}

void CDataTranSrv::tcpCli2Error(QAbstractSocket::SocketError socketError)
{
    STcpClient* pTcpClient = m_plstTcpClient->at(1);
    TcpClientError(socketError, pTcpClient);
}

void CDataTranSrv::tcpCli3Error(QAbstractSocket::SocketError socketError)
{
    STcpClient* pTcpClient = m_plstTcpClient->at(2);
    TcpClientError(socketError, pTcpClient);
}

void CDataTranSrv::tcpCli4Error(QAbstractSocket::SocketError socketError)
{
    STcpClient* pTcpClient = m_plstTcpClient->at(3);
    TcpClientError(socketError, pTcpClient);
}

void CDataTranSrv::tcpCli5Error(QAbstractSocket::SocketError socketError)
{
    STcpClient* pTcpClient = m_plstTcpClient->at(4);
    TcpClientError(socketError, pTcpClient);
}

void CDataTranSrv::tcpCli6Error(QAbstractSocket::SocketError socketError)
{
    STcpClient* pTcpClient = m_plstTcpClient->at(5);
    TcpClientError(socketError, pTcpClient);
}

void CDataTranSrv::tcpCli7Error(QAbstractSocket::SocketError socketError)
{
    STcpClient* pTcpClient = m_plstTcpClient->at(6);
    TcpClientError(socketError, pTcpClient);
}

void CDataTranSrv::tcpCli8Error(QAbstractSocket::SocketError socketError)
{
    STcpClient* pTcpClient = m_plstTcpClient->at(7);
    TcpClientError(socketError, pTcpClient);
}

void CDataTranSrv::tcpCli9Error(QAbstractSocket::SocketError socketError)
{
    STcpClient* pTcpClient = m_plstTcpClient->at(8);
    TcpClientError(socketError, pTcpClient);
}

void CDataTranSrv::tcpCli10Error(QAbstractSocket::SocketError socketError)
{
    STcpClient* pTcpClient = m_plstTcpClient->at(9);
    TcpClientError(socketError, pTcpClient);
}

void CDataTranSrv::tcpCli11Error(QAbstractSocket::SocketError socketError)
{
    STcpClient* pTcpClient = m_plstTcpClient->at(10);
    TcpClientError(socketError, pTcpClient);
}

void CDataTranSrv::tcpCli12Error(QAbstractSocket::SocketError socketError)
{
    STcpClient* pTcpClient = m_plstTcpClient->at(11);
    TcpClientError(socketError, pTcpClient);
}

void CDataTranSrv::tcpCli13Error(QAbstractSocket::SocketError socketError)
{
    STcpClient* pTcpClient = m_plstTcpClient->at(12);
    TcpClientError(socketError, pTcpClient);
}

void CDataTranSrv::tcpCli14Error(QAbstractSocket::SocketError socketError)
{
    STcpClient* pTcpClient = m_plstTcpClient->at(13);
    TcpClientError(socketError, pTcpClient);
}

void CDataTranSrv::tcpCli15Error(QAbstractSocket::SocketError socketError)
{
    STcpClient* pTcpClient = m_plstTcpClient->at(14);
    TcpClientError(socketError, pTcpClient);
}

void CDataTranSrv::tcpCli16Error(QAbstractSocket::SocketError socketError)
{
    STcpClient* pTcpClient = m_plstTcpClient->at(15);
    TcpClientError(socketError, pTcpClient);
}

void CDataTranSrv::tcpCli17Error(QAbstractSocket::SocketError socketError)
{
    STcpClient* pTcpClient = m_plstTcpClient->at(16);
    TcpClientError(socketError, pTcpClient);
}

void CDataTranSrv::tcpCli1ReadDatagram()
{
	STcpClient* pTcpClient = m_plstTcpClient->at(0);
	if (pTcpClient && pTcpClient->pTcpSocket)
	{
		tcpCliReadDatagram(pTcpClient->pTcpSocket, pTcpClient->pDataBuf);
		pTcpClient->iIdleTimeCount = 0;
		msleep(3);
	}
}

void CDataTranSrv::tcpCli2ReadDatagram()
{
	STcpClient* pTcpClient = m_plstTcpClient->at(1);
	if (pTcpClient && pTcpClient->pTcpSocket)
	{
		tcpCliReadDatagram(pTcpClient->pTcpSocket, pTcpClient->pDataBuf);
		pTcpClient->iIdleTimeCount = 0;
		msleep(3);
	}
}

void CDataTranSrv::tcpCli3ReadDatagram()
{
	STcpClient* pTcpClient = m_plstTcpClient->at(2);
	if (pTcpClient && pTcpClient->pTcpSocket)
	{
		tcpCliReadDatagram(pTcpClient->pTcpSocket, pTcpClient->pDataBuf);
		pTcpClient->iIdleTimeCount = 0;
		msleep(3);
	}
}

void CDataTranSrv::tcpCli4ReadDatagram()
{
	STcpClient* pTcpClient = m_plstTcpClient->at(3);
	if (pTcpClient && pTcpClient->pTcpSocket)
	{
		tcpCliReadDatagram(pTcpClient->pTcpSocket, pTcpClient->pDataBuf);
		pTcpClient->iIdleTimeCount = 0;
		msleep(3);
	}
}

void CDataTranSrv::tcpCli5ReadDatagram()
{
	STcpClient* pTcpClient = m_plstTcpClient->at(4);
	if (pTcpClient && pTcpClient->pTcpSocket)
	{
		tcpCliReadDatagram(pTcpClient->pTcpSocket, pTcpClient->pDataBuf);
		pTcpClient->iIdleTimeCount = 0;
		msleep(3);
	}
}

void CDataTranSrv::tcpCli6ReadDatagram()
{
	STcpClient* pTcpClient = m_plstTcpClient->at(5);
	if (pTcpClient && pTcpClient->pTcpSocket)
	{
		tcpCliReadDatagram(pTcpClient->pTcpSocket, pTcpClient->pDataBuf);
		pTcpClient->iIdleTimeCount = 0;
		msleep(3);
	}
}

void CDataTranSrv::tcpCli7ReadDatagram()
{
	STcpClient* pTcpClient = m_plstTcpClient->at(6);
	if (pTcpClient && pTcpClient->pTcpSocket)
	{
		tcpCliReadDatagram(pTcpClient->pTcpSocket, pTcpClient->pDataBuf);
		pTcpClient->iIdleTimeCount = 0;
		msleep(3);
	}
}

void CDataTranSrv::tcpCli8ReadDatagram()
{
	STcpClient* pTcpClient = m_plstTcpClient->at(7);
	if (pTcpClient && pTcpClient->pTcpSocket)
	{
		tcpCliReadDatagram(pTcpClient->pTcpSocket, pTcpClient->pDataBuf);
		pTcpClient->iIdleTimeCount = 0;
		msleep(3);
	}
}

void CDataTranSrv::tcpCli9ReadDatagram()
{
	STcpClient* pTcpClient = m_plstTcpClient->at(8);
	if (pTcpClient && pTcpClient->pTcpSocket)
	{
		tcpCliReadDatagram(pTcpClient->pTcpSocket, pTcpClient->pDataBuf);
		pTcpClient->iIdleTimeCount = 0;
		msleep(3);
	}
}

void CDataTranSrv::tcpCli10ReadDatagram()
{
	STcpClient* pTcpClient = m_plstTcpClient->at(9);
	if (pTcpClient && pTcpClient->pTcpSocket)
	{
		tcpCliReadDatagram(pTcpClient->pTcpSocket, pTcpClient->pDataBuf);
		pTcpClient->iIdleTimeCount = 0;
		msleep(3);
	}
}

void CDataTranSrv::tcpCli11ReadDatagram()
{
	STcpClient* pTcpClient = m_plstTcpClient->at(10);
	if (pTcpClient && pTcpClient->pTcpSocket)
	{
		tcpCliReadDatagram(pTcpClient->pTcpSocket, pTcpClient->pDataBuf);
		pTcpClient->iIdleTimeCount = 0;
		msleep(3);
	}
}

void CDataTranSrv::tcpCli12ReadDatagram()
{
	STcpClient* pTcpClient = m_plstTcpClient->at(11);
	if (pTcpClient && pTcpClient->pTcpSocket)
	{
		tcpCliReadDatagram(pTcpClient->pTcpSocket, pTcpClient->pDataBuf);
		pTcpClient->iIdleTimeCount = 0;
		msleep(3);
	}
}

void CDataTranSrv::tcpCli13ReadDatagram()
{
	STcpClient* pTcpClient = m_plstTcpClient->at(12);
	if (pTcpClient && pTcpClient->pTcpSocket)
	{
		tcpCliReadDatagram(pTcpClient->pTcpSocket, pTcpClient->pDataBuf);
		pTcpClient->iIdleTimeCount = 0;
		msleep(3);
	}
}

void CDataTranSrv::tcpCli14ReadDatagram()
{
	STcpClient* pTcpClient = m_plstTcpClient->at(13);
	if (pTcpClient && pTcpClient->pTcpSocket)
	{
		tcpCliReadDatagram(pTcpClient->pTcpSocket, pTcpClient->pDataBuf);
		pTcpClient->iIdleTimeCount = 0;
		msleep(3);
	}
}

void CDataTranSrv::tcpCli15ReadDatagram()
{
	STcpClient* pTcpClient = m_plstTcpClient->at(14);
	if (pTcpClient && pTcpClient->pTcpSocket)
	{
		tcpCliReadDatagram(pTcpClient->pTcpSocket, pTcpClient->pDataBuf);
		pTcpClient->iIdleTimeCount = 0;
		msleep(3);
	}
}

void CDataTranSrv::tcpCli16ReadDatagram()
{
	STcpClient* pTcpClient = m_plstTcpClient->at(15);
	if (pTcpClient && pTcpClient->pTcpSocket)
	{
		tcpCliReadDatagram(pTcpClient->pTcpSocket, pTcpClient->pDataBuf);
		pTcpClient->iIdleTimeCount = 0;
		msleep(3);
	}
}

void CDataTranSrv::tcpCli17ReadDatagram()
{
	STcpClient* pTcpClient = m_plstTcpClient->at(16);
	if (pTcpClient && pTcpClient->pTcpSocket)
	{
		tcpCliReadDatagram(pTcpClient->pTcpSocket, pTcpClient->pDataBuf);
		pTcpClient->iIdleTimeCount = 0;
		msleep(3);
	}
}

//接收从站的请求数据,解析并填充应答数据,回复给从站
void CDataTranSrv::tcpCliReadDatagram(QTcpSocket* pTcpClient, char* pDataBuf)
{
    if (0 == pTcpClient || 0 == pDataBuf)
	{
		return;
	}

	// pTcpClient->bytesAvailable() < (int)sizeof(quint16)
	SMdobusTcpReq req;
	CBattBank* pBattBank = 0;
	CBankAlarm* pBankAlarm = 0;
	CBAComReg* pBAComReg = 0;
	int iRetVal = pTcpClient->read(pDataBuf, SNED_BUFFER_LENGHT);

    if (iRetVal >= 12) //read OK 2事务处理标识+2协议标识+2长度+1单元标识/Modbus地址+1功能码+2寄存器地址+2寄存器数量
	{
		m_iCheckEMSLinkCount = 0;
		printReceInfo(pTcpClient->peerAddress().toString(), pDataBuf, iRetVal);

		iRetVal = m_pModbusFactory->analyReqDatagram(pDataBuf, iRetVal, req);

		if (0 == iRetVal)
		{
            int iModbusAddress = req.uaAddr - m_uaModbusAddrOffset;
            // 组报文
            if (CModbusAddress::IsStackData(iModbusAddress)) //电池堆
			{
                DoStackData(pTcpClient, pDataBuf, req);
			}
            else if (CModbusAddress::IsEnvData(iModbusAddress)) //动环测量
			{
                DoEnvData(pTcpClient, pDataBuf, req, iModbusAddress);
			}
            else if (CModbusAddress::IsHoldReg(iModbusAddress)) //通用保持寄存器
			{
                DoHoldReg(pTcpClient, pDataBuf, req);
			}
            else if (CModbusAddress::IsInputReg(iModbusAddress)) //通用输入寄存器
			{
                DoInputReg(pTcpClient, pDataBuf, req);
			}
            else if (CModbusAddress::IsBankData(iModbusAddress)) //电池簇
			{
                DoBankData(pTcpClient, pDataBuf, req);
			}
        }
	}
}

void CDataTranSrv::DoStackData(QTcpSocket* pTcpClient, char* pDataBuf, SMdobusTcpReq& req)
{
    if (0 == pTcpClient)
    {
        return;
    }

    if (0 == pDataBuf)
    {
        return;
    }

    int iRetVal = m_pModbusFactory->prepareStackDatagram(pDataBuf, &req, m_pBattStack);

    if (iRetVal >= 0)
    {
        printSendInfo(pTcpClient->peerAddress().toString(), pDataBuf, iRetVal);

        if (iRetVal != pTcpClient->write(pDataBuf, iRetVal))
        {
            KG_LOG_INFO(QString("向tcp客户端(%1)写电池堆数据时失败").arg(pTcpClient->peerAddress().toString()));
        }
        else
        {
            pTcpClient->flush();
        }
    }
    else
    {
        sendExcepDatagram(pTcpClient, pDataBuf, &req, 1);
        KG_LOG_INFO(QString("分析电池堆数据时失败，tcp客户端(%1)").arg(pTcpClient->peerAddress().toString()));
    }
}

void CDataTranSrv::DoBankData(QTcpSocket* pTcpClient, char* pDataBuf, SMdobusTcpReq& req)
{
    if (0 == pTcpClient)
    {
        return;
    }

    if (0 == pDataBuf)
    {
        return;
    }

    CBattBank* pBattBank = 0; //电池组信息
    CBankAlarm* pBankAlarm = 0; //电池组告警

    int iBankIndex = req.uaAddr - 2 - m_uaModbusAddrOffset;
    if (iBankIndex < MAX_BANK_NUM && iBankIndex >= 0)
    {
        pBankAlarm = m_pRTDB->getBankAlarm(iBankIndex);
        pBattBank = m_pRTDB->getBank(iBankIndex);
    }

    if (0 == pBattBank || 0 == pBankAlarm)
    {
        sendExcepDatagram(pTcpClient, pDataBuf, &req, 1);
        KG_LOG_INFO(QString("未找到电池组. tcp客户端(%1), 请先确认modbus地址:%2 iBankIndex=%3").arg(pTcpClient->peerAddress().toString()).arg(req.uaAddr).arg(iBankIndex));
        return;
    }

    int iRetVal = 0;
    if (3 == req.uaFuncCode || 6 == req.uaFuncCode || 16 == req.uaFuncCode) //保持寄存器 - 告警参数
    {
        iRetVal = m_pModbusFactory->prepareBankAlarmDatagram(pDataBuf, &req,  &(pBankAlarm->param), pBattBank, m_pBattStack);

        if (iRetVal >= 0)
        {
            printSendInfo(pTcpClient->peerAddress().toString(), pDataBuf, iRetVal);

            if (iRetVal != pTcpClient->write(pDataBuf, iRetVal))
            {

                KG_LOG_INFO(QString("向tcp客户端(%1)写电池组告警数据时失败").arg(pTcpClient->peerAddress().toString()));
            }
            else
            {
                pTcpClient->flush();
            }
        }
        else
        {
            sendExcepDatagram(pTcpClient, pDataBuf, &req, 1);
            KG_LOG_INFO(QString("分析电池组告警数据时失败，tcp客户端(%1)").arg(pTcpClient->peerAddress().toString()));
        }
    }
    else if (17 == req.uaFuncCode) //告警缓存 0x11
    {
        if (1 == m_pBattStack->usAlarmCacheStrategy)
        {
            m_pAlmCacheSem[req.uaAddr - 2]->acquire();
            iRetVal = m_pModbusFactory->prepareAlarmCacheDatagram(pDataBuf, &req, pBattBank, pBankAlarm);
            m_pAlmCacheSem[req.uaAddr - 2]->release();

            if (iRetVal > 0) //iRetVal = 0 不处理
            {
                printSendInfo(pTcpClient->peerAddress().toString(), pDataBuf, iRetVal);

                if (iRetVal != pTcpClient->write(pDataBuf, iRetVal))
                {
                    emit addLog(RUN_LOG_FAILED, QString("Write data to tcp client(%1) FAILED.").arg(pTcpClient->peerAddress().toString()));
                }
                else
                {
                    pTcpClient->flush();
                }
            }
            else if (iRetVal < 0)
            {
                sendExcepDatagram(pTcpClient, pDataBuf, &req, 1);
                emit addLog(RUN_LOG_FAILED, QString("Analy prepare Alarm Cache Datagram FAILED. Client %1.").arg(pTcpClient->peerAddress().toString()));
            }
        }
        else
        {
            sendExcepDatagram(pTcpClient, pDataBuf, &req, 1);
            emit addLog(RUN_LOG_FAILED, QString("Not find Batt Bank. Client %1, Please confirm modbus addr:%2.").arg(pTcpClient->peerAddress().toString()).arg(req.uaAddr));
        }
    }
    else
    {
        iRetVal = m_pModbusFactory->prepareBattDatagram(pDataBuf, &req, pBattBank);

        if (iRetVal >= 0)
        {
            printSendInfo(pTcpClient->peerAddress().toString(), pDataBuf, iRetVal);

            if (iRetVal != pTcpClient->write(pDataBuf, iRetVal))
            {
                KG_LOG_INFO(QString("向tcp客户端(%1)写电池堆数据时失败").arg(pTcpClient->peerAddress().toString()));
            }
            else
            {
                pTcpClient->flush();
            }
        }
        else
        {
            sendExcepDatagram(pTcpClient, pDataBuf, &req, 1);
            emit addLog(RUN_LOG_FAILED, QString("Analy prepare Bank Datagram FAILED. Client %1.").arg(pTcpClient->peerAddress().toString()));
        }
    }
}

void CDataTranSrv::DoEnvData(QTcpSocket* pTcpClient, char* pDataBuf, SMdobusTcpReq& req, int iModbusAddress)
{
    if (0 == pTcpClient)
    {
        return;
    }

    if (0 == pDataBuf)
    {
        return;
    }

    int iRetVal = m_pModbusFactory->prepareEnvDatagram(pDataBuf, &req, m_pBattStack, iModbusAddress);

    if (iRetVal >= 0)
    {
        printSendInfo(pTcpClient->peerAddress().toString(), pDataBuf, iRetVal);

        if (iRetVal != pTcpClient->write(pDataBuf, iRetVal))
        {
            KG_LOG_INFO(QString("向tcp客户端(%1)写动环应答数据时失败").arg(pTcpClient->peerAddress().toString()));
        }
        else
        {
            pTcpClient->flush();
        }
    }
    else
    {
        sendExcepDatagram(pTcpClient, pDataBuf, &req, 1);
        KG_LOG_INFO(QString("准备动环应答数据时失败，tcp客户端(%1) iRetVal=%2").arg(pTcpClient->peerAddress().toString()).arg(iRetVal));
    }
}

void CDataTranSrv::DoHoldReg(QTcpSocket* pTcpClient, char* pDataBuf, SMdobusTcpReq& req)
{
    if (0 == pTcpClient)
    {
        return;
    }

    if (0 == pDataBuf)
    {
        return;
    }

    CBAComReg* pBAComReg = 0;
    pBAComReg = m_pRTDB->getBAComReg(0);
    if (0 == pBAComReg)
    {
        sendExcepDatagram(pTcpClient, pDataBuf, &req, 1);
        KG_LOG_INFO(QString("分析通用寄存器数据时失败，tcp客户端(%1)").arg(pTcpClient->peerAddress().toString()));
        return;
    }

    int iRetVal = m_pModbusFactory->prepareBAComHoldRegDatagram(pDataBuf, &req, pBAComReg->usComHoldRegVal);

    if (iRetVal >= 0)
    {
        printSendInfo(pTcpClient->peerAddress().toString(), pDataBuf, iRetVal);

        if (iRetVal != pTcpClient->write(pDataBuf, iRetVal))
        {
            KG_LOG_INFO(QString("向tcp客户端(%1)写保存寄存器数据时失败").arg(pTcpClient->peerAddress().toString()));
        }
        else
        {
            pTcpClient->flush();
        }
    }
    else
    {
        sendExcepDatagram(pTcpClient, pDataBuf, &req, 1);
        KG_LOG_INFO(QString("分析保存寄存器数据时失败，tcp客户端(%1)").arg(pTcpClient->peerAddress().toString()));
    }
}

void CDataTranSrv::DoInputReg(QTcpSocket* pTcpClient, char* pDataBuf, SMdobusTcpReq& req)
{
    if (0 == pTcpClient)
    {
        return;
    }

    if (0 == pDataBuf)
    {
        return;
    }

    CBAComReg* pBAComReg = 0;
    pBAComReg = m_pRTDB->getBAComReg(0);
    if (0 == pBAComReg)
    {
        sendExcepDatagram(pTcpClient, pDataBuf, &req, 1);
        KG_LOG_INFO(QString("分析输入寄存器数据时失败，tcp客户端(%1)").arg(pTcpClient->peerAddress().toString()));
        return;
    }

    int iRetVal = m_pModbusFactory->prepareBAComInputRegDatagram(pDataBuf, &req, pBAComReg->usComInputRegVal);

    if (iRetVal >= 0)
    {
        printSendInfo(pTcpClient->peerAddress().toString(), pDataBuf, iRetVal);

        if (iRetVal != pTcpClient->write(pDataBuf, iRetVal))
        {
            KG_LOG_INFO(QString("向tcp客户端(%1)写输入寄存器数据时失败").arg(pTcpClient->peerAddress().toString()));
        }
        else
        {
            pTcpClient->flush();
        }
    }
    else
    {
        sendExcepDatagram(pTcpClient, pDataBuf, &req, 1);
        KG_LOG_INFO(QString("分析输入寄存器数据时失败，tcp客户端(%1)").arg(pTcpClient->peerAddress().toString()));
    }
}

void CDataTranSrv::sendExcepDatagram(QTcpSocket* pTcpClient, char* pDataBuf, SMdobusTcpReq* pReq, uchar uaExcepCode)
{
    if (0 == pTcpClient || 0 == pDataBuf || 0 == pReq)
	{
		return;
	}

	int iLen = m_pModbusFactory->prepareExcepDatagram(pDataBuf, pReq, uaExcepCode); //>= 0 OK  -1 准备失败  
	if (iLen >= 0) 
	{
		printSendInfo(pTcpClient->peerAddress().toString(), pDataBuf, iLen);

		if (iLen != pTcpClient->write(pDataBuf, iLen))
		{
            KG_LOG_INFO(QString("向tcp客户端(%1)写异常错误数据时失败").arg(pTcpClient->peerAddress().toString()));
		}
		else
		{
			pTcpClient->flush();
		}
	}
}

void CDataTranSrv::printSendInfo(const QString& strCliIP, char* pBufData, int iLen)
{
	QString strPrintInfo = "";
	QChar aFillChar = '0';

	for (int i = 0; i < iLen; ++i)
	{
		strPrintInfo += QString("%1 ").arg((uchar)*(pBufData + i), 2, 16, aFillChar);
	}

	strPrintInfo = strPrintInfo.toUpper();

    strPrintInfo =  "发给:" + strCliIP + " 应答报文:" + strPrintInfo;

    KG_LOG_INFO(strPrintInfo);
}

void CDataTranSrv::printReceInfo(const QString& strCliIP, char* pBufData, int iLen)
{
	QString strPrintInfo = "";
	QChar aFillChar = '0';

	for (int i = 0; i < iLen; ++i)
	{
		strPrintInfo += QString("%1 ").arg((uchar)*(pBufData + i), 2, 16, aFillChar);
	}

	strPrintInfo = strPrintInfo.toUpper();

    strPrintInfo = "接收:" + strCliIP + " 请求报文:" + strPrintInfo;

    KG_LOG_INFO(strPrintInfo);
}

void CDataTranSrv::setPort(ushort usPort)
{
	m_usPort = usPort;
}

void CDataTranSrv::setCliIdleTime(int iIdleTime)
{
	m_iIdleTime = iIdleTime;

	if (m_iIdleTime < 5)
	{
		m_iIdleTime = 5; //最小5秒
	}
}

void CDataTranSrv::setModbusAddrOffset(uchar uaModbusAddrOffset)
{
	m_uaModbusAddrOffset = uaModbusAddrOffset;
}

void CDataTranSrv::SetProjectMode(int iProjectMode)
{
    m_iProjectMode = iProjectMode;
}

void CDataTranSrv::run()
{
	// some variables
    if (m_pBattStack)
    {//让ui在语言变更时进行响应更新
        if (m_iOrgLang != m_pBattStack->usLang)
        {
            m_iOrgLang = m_pBattStack->usLang;

            emit switchLang();//发出切换语言的信号
        }
    }

	quint16 usStackCfgInfo = 0;
	int iBankIndex = 0;
	QDateTime dtStart = QDateTime::currentDateTime();

	CBattBank* pBattBank = 0;
	quint16 usStackState = 0xbbbb; //以等级最低为初始值  0xbbbb - 正常
	quint16 usBankStateSum = 0;
	
	float fStackVol = 0; //电池堆总电压         
	int iStackVolNum = 0; 
	float fStackCur = 0; //电池堆总电流 
	float fStackSoc = 0; //电池堆SOC ，荷电状态   
	float fStackInsuRes = 9999; //系统绝缘
	int iStackSocNum = 0;
    float fStackSoh = 0; //电池堆SOH， 健康状态
    int iStackSohNum = 0;

    float fStackChargeEQ = 0; //电池堆可充电量
    float fStackDischargeEQ = 0; //电池堆可放电量
    float fStackSglChargeEQ = 0; //电池堆单次充电电量
    float fStackSglDischargeEQ = 0; //电池堆单次放电电量
    float fStackSglChargeAh = 0; //电池堆单次充电容量
    float fStackSglDischargeAh = 0; //电池堆单次放电容量

    double dblStackChargeEQAdd = 0; //电池堆充电量累加值
    double dblStackDischargeEQAdd = 0; //电池堆放电量累加值
    double dblStackChargeAhAdd = 0; //电池堆充容量累加值
    double dblStackDischargeAhAdd = 0; //电池堆放容量累加值
	
    float fBankMaxChargePowerAdd = 0; //电池堆最大充电功率
    float fBankMaxDischargePowerAdd = 0; //电池堆最大放电功率
    float fBankMaxChargeCurrentAdd = 0; //电池堆最大充电电流
    float fBankMaxDischargeCurrentAdd = 0; //电池堆最大放电电流

    float fLastBankMaxChargePowerAdd = m_pBattStack->fBankMaxChargePower * m_pBattStack->usBankNumInStack; //上次组最大充电功率累加
    float fLastBankMaxDischargePowerAdd = m_pBattStack->fBankMaxDischargePower * m_pBattStack->usBankNumInStack; //上次组最大放电功率累加
    float fLastBankMaxChargeCurrentAdd = m_pBattStack->fBankMaxChargeCurrent * m_pBattStack->usBankNumInStack; //上次组最大充电电流累加
    float fLastBankMaxDischargeCurrentAdd = m_pBattStack->fBankMaxDischargeCurrent * m_pBattStack->usBankNumInStack; //上次组最大放电电流累加

	float fLastStackMaxChargePower = m_pBattStack->fBankMaxChargePower * m_pBattStack->usBankNumInStack; //上次电池堆最大充电功率
	float fLastStackMaxDischargePower = m_pBattStack->fBankMaxDischargePower * m_pBattStack->usBankNumInStack; //上次电池堆最大放电功率   
	float fLastStackMaxChargeCurrent = m_pBattStack->fBankMaxChargeCurrent * m_pBattStack->usBankNumInStack; //上次电池堆最大充电电流   
    float fLastStackMaxDischargeCurrent = m_pBattStack->fBankMaxDischargeCurrent * m_pBattStack->usBankNumInStack; //上次电池堆最大放电电流

	bool bAllBankChg = true; //各组全充电
	bool bAllBankDchg = true; //各组全放电

	quint16 usIsolSwitchAggrState = 1; //隔离开关状态

	// 组间统计
	quint16 usBankSocMaxBankNo = ALARM_BANK_NO;
	quint16 usBankSocMinBankNo = ALARM_BANK_NO; 

	quint16 usBankVolMaxBankNo = ALARM_BANK_NO;
	quint16 usBankVolMinBankNo = ALARM_BANK_NO;

	quint16 usBankCurMaxBankNo = ALARM_BANK_NO;
	quint16 usBankCurMinBankNo = ALARM_BANK_NO;

	quint16 usSglMaxVolBankNo = ALARM_BANK_NO; 
	quint16 usSglMaxVolNoInBank = ALARM_BANK_NO;
	quint16 usSglMinVolBankNo = ALARM_BANK_NO; 
	quint16 usSglMinVolNoInBank = ALARM_BANK_NO;

	quint16 usSglMaxTempBankNo = ALARM_BANK_NO;
	quint16 usSglMaxTempNoInBank = ALARM_BANK_NO;
	quint16 usSglMinTempBankNo = ALARM_BANK_NO;
	quint16 usSglMinTempNoInBank = ALARM_BANK_NO;

	float fBankSocMax = 0;
	float fBankSocMin = 0;

	float fBankVolMax = 0;
	float fBankVolMin = 0;

	float fBankCurMax = 0;
	float fBankCurMin = 0;

	float fSglMaxVolInStack = 0;
	float fSglMinVolInStack = 0; 
	float fSglMaxTempInStack = 0;
	float fSglMinTempInStack = 0;

	bool bNeedClearFault = false;

	while (true)
	{
		msleep(500);

		// init variables
		dtStart = QDateTime::currentDateTime();

		pBattBank = 0;
		usStackState = 0xbbbb; //以等级最低为初始值  0xbbbb - 正常
		usBankStateSum = 0;

		fStackVol = 0; //电池堆总电压         
		iStackVolNum = 0; 
		fStackCur = 0; //电池堆总电流 
		fStackInsuRes = 9999; //系统绝缘
		fStackSoc = 0; //电池堆SOC             
		iStackSocNum = 0;
		fStackSoh = 0; //电池堆SOH             
		iStackSohNum = 0; 

		fStackChargeEQ = 0; //电池堆可充电量        
		fStackDischargeEQ = 0; //电池堆可放电量  
		fStackSglChargeEQ = 0; //电池堆单次充电电量 
		fStackSglDischargeEQ = 0; //电池堆单次放电电量 		  
		fStackSglChargeAh = 0; //电池堆单次充电容量 
		fStackSglDischargeAh = 0; //电池堆单次放电容量 		 

		dblStackChargeEQAdd = 0; //电池堆充电量累加值   
		dblStackDischargeEQAdd = 0; //电池堆放电量累加值  
		dblStackChargeAhAdd = 0; //电池堆充容量累加值   
		dblStackDischargeAhAdd = 0; //电池堆放容量累加值

		fBankMaxChargePowerAdd = 0; //电池堆最大充电功率    
		fBankMaxDischargePowerAdd = 0; //电池堆最大放电功率   
		fBankMaxChargeCurrentAdd = 0; //电池堆最大充电电流   
		fBankMaxDischargeCurrentAdd = 0; //电池堆最大放电电流   

		bAllBankChg = true; //各组全充电
		bAllBankDchg = true; //各组全放电
		usIsolSwitchAggrState = 1; //隔离开关状态

		// 组间统计
		usBankSocMaxBankNo = ALARM_BANK_NO;
		usBankSocMinBankNo = ALARM_BANK_NO; 
		usBankVolMaxBankNo = ALARM_BANK_NO;
		usBankVolMinBankNo = ALARM_BANK_NO; 
		usBankCurMaxBankNo = ALARM_BANK_NO;
		usBankCurMinBankNo = ALARM_BANK_NO;
		usSglMaxVolBankNo = ALARM_BANK_NO;
		usSglMaxVolNoInBank = ALARM_BANK_NO;
		usSglMinVolBankNo = ALARM_BANK_NO;
		usSglMinVolNoInBank = ALARM_BANK_NO;
		usSglMaxTempBankNo = ALARM_BANK_NO;
		usSglMaxTempNoInBank = ALARM_BANK_NO;
		usSglMinTempBankNo = ALARM_BANK_NO;
		usSglMinTempNoInBank = ALARM_BANK_NO;
		fBankSocMax = 0;
		fBankSocMin = 0;
		fBankVolMax = 0;
		fBankVolMin = 0;
		fBankCurMax = 0;
		fBankCurMin = 0;
		fSglMaxVolInStack = 0;
		fSglMinVolInStack = 0;
		fSglMaxTempInStack = 0;
		fSglMinTempInStack = 0;

        if (m_pBattStack->usEMSFaultClearModifyCount > 0 && m_pBattStack->usEMSFaultClearModifyCount < 10) //已远程设置
		{
			m_pBattStack->usEMSFaultClearModifyCount += 10;
			bNeedClearFault = true;
		}
		else
		{
			bNeedClearFault = false;
		}
		
		// 电池堆状态计算
		usStackCfgInfo = m_pBattStack->usStackCfgInfo;
		iBankIndex = 0;
		while(usStackCfgInfo > 0)
		{
            if ((usStackCfgInfo & 0x0001) > 0) //该组参与运算
			{
				if (iBankIndex >= m_pBattStack->usInstallBankNum)
				{
					break;
				}

				pBattBank = m_pRTDB->getBank(iBankIndex);
				if (pBattBank) //单组
				{
					calculateState(usStackState, pBattBank->usBankState);

					// 状态汇总
					if (0x1111 == pBattBank->usBankState && ((pBattBank->usForbidReason & 0x0100) > 0)) //充满导致的禁充
					{
						usBankStateSum |= 0x0001;
					}
					else if (0x2222 == pBattBank->usBankState && ((pBattBank->usForbidReason & 0x0001) > 0)) //放空导致的禁放
					{
						usBankStateSum |= 0x0002;
					}

					// 电池堆总电压
					if (pBattBank->fBankVol > BANK_VOL_SAMPLE_INVALID_VALUE_DOWN && pBattBank->fBankVol < BANK_VOL_SAMPLE_INVALID_VALUE_UP)
					{
						fStackVol += pBattBank->fBankVol;
						++iStackVolNum;
					}

					if (pBattBank->fBankCur > BANK_CUR_SAMPLE_INVALID_VALUE_DOWN && pBattBank->fBankCur < BANK_CUR_SAMPLE_INVALID_VALUE_UP)
					{
						fStackCur += pBattBank->fBankCur; //电池堆总电流
					}

					// 系统绝缘
					if (fStackInsuRes > pBattBank->fBankInsuRes)
					{
						fStackInsuRes = pBattBank->fBankInsuRes;
					}

					if (pBattBank->fBankSoc > -0.001 && pBattBank->fBankSoc < SOC_SAMPLE_INVALID_VALUE_UP)
					{
						fStackSoc += pBattBank->fBankSoc;
						++iStackSocNum;
					}

					if (pBattBank->fBankSoh > 0 && pBattBank->fBankSoh < SOH_SAMPLE_INVALID_VALUE_UP)
					{
						fStackSoh += pBattBank->fBankSoh;
						++iStackSohNum;
					}

					fStackChargeEQ += pBattBank->fBankChargeEQ;
					fStackDischargeEQ += pBattBank->fBankDischargeEQ;
					fStackSglChargeEQ += pBattBank->fBankSglChargeEQ;
					fStackSglDischargeEQ += pBattBank->fBankSglDischargeEQ;
					fStackSglChargeAh += pBattBank->fBankSglChargeAh;
					fStackSglDischargeAh += pBattBank->fBankSglDischargeAh;
					dblStackChargeEQAdd += pBattBank->dblBankChargeEQAdd;
					dblStackDischargeEQAdd += pBattBank->dblBankDischargeEQAdd;
					dblStackChargeAhAdd += pBattBank->dblBankChargeAhAdd;
					dblStackDischargeAhAdd += pBattBank->dblBankDischargeAhAdd;

					fBankMaxChargePowerAdd += pBattBank->fBankAllowMaxChargePower;
					fBankMaxDischargePowerAdd += pBattBank->fBankAllowMaxDischargePower;
					fBankMaxChargeCurrentAdd += pBattBank->fBankAllowMaxChargeCurrent;
					fBankMaxDischargeCurrentAdd += pBattBank->fBankAllowMaxDischargeCurrent;
								
					if (!(pBattBank->fBankCur < -2)) //各组全放电
					{
						bAllBankDchg = false;
					}
								
					if (!(pBattBank->fBankCur > 2)) //各组全充电
					{
						bAllBankChg = false;
					}
					
					if (1 == m_pBattStack->usIsolSwitchStrategy && 0 == pBattBank->usDI3) //隔离开关反馈 BC 的DI3
					{
						usIsolSwitchAggrState = 0;
					}
					else if (2 == m_pBattStack->usIsolSwitchStrategy && 0 == pBattBank->usDI4) //隔离开关反馈 BC 的DI4
					{
						usIsolSwitchAggrState = 0;
					}
						
					// 组间统计
					if (ALARM_BANK_NO == usBankSocMaxBankNo || pBattBank->fBankSoc > fBankSocMax)
					{
						usBankSocMaxBankNo = (quint16)(iBankIndex + 1);
						fBankSocMax = pBattBank->fBankSoc;
					}

                    if (ALARM_BANK_NO == usBankSocMinBankNo || pBattBank->fBankSoc < fBankSocMin)
					{
						usBankSocMinBankNo = (quint16)(iBankIndex + 1);
						fBankSocMin = pBattBank->fBankSoc;
					}

                    if (ALARM_BANK_NO == usBankVolMaxBankNo || pBattBank->fBankVol > fBankVolMax)
					{
						usBankVolMaxBankNo = (quint16)(iBankIndex + 1);
						fBankVolMax = pBattBank->fBankVol;
					}

                    if (ALARM_BANK_NO == usBankVolMinBankNo || pBattBank->fBankVol < fBankVolMin)
					{
						usBankVolMinBankNo = (quint16)(iBankIndex + 1);
						fBankVolMin = pBattBank->fBankVol;
					}

                    if (ALARM_BANK_NO == usBankCurMaxBankNo || pBattBank->fBankCur > fBankCurMax)
					{
						usBankCurMaxBankNo = (quint16)(iBankIndex + 1);
						fBankCurMax = pBattBank->fBankCur;
					}

                    if (ALARM_BANK_NO == usBankCurMinBankNo || pBattBank->fBankCur < fBankCurMin)
					{
						usBankCurMinBankNo = (quint16)(iBankIndex + 1);
						fBankCurMin = pBattBank->fBankCur;
					}

					if (ALARM_BANK_NO == usSglMaxVolBankNo || pBattBank->fSglMaxVol > fSglMaxVolInStack)
					{
						usSglMaxVolBankNo = (quint16)(iBankIndex + 1);
						usSglMaxVolNoInBank = pBattBank->usSglMaxVolNo;
						fSglMaxVolInStack =  pBattBank->fSglMaxVol;
					}

					if (ALARM_BANK_NO == usSglMinVolBankNo || pBattBank->fSglMinVol < fSglMinVolInStack)
					{
						usSglMinVolBankNo = (quint16)(iBankIndex + 1);
						usSglMinVolNoInBank = pBattBank->usSglMinVolNo;
						fSglMinVolInStack =  pBattBank->fSglMinVol;
					}

					if (ALARM_BANK_NO == usSglMaxTempBankNo || pBattBank->fSglMaxTemp > fSglMaxTempInStack)
					{
						usSglMaxTempBankNo = (quint16)(iBankIndex + 1);
						usSglMaxTempNoInBank = pBattBank->usSglMaxTempNo;
						fSglMaxTempInStack =  pBattBank->fSglMaxTemp;
					}

					if (ALARM_BANK_NO == usSglMinTempBankNo || pBattBank->fSglMinTemp < fSglMinTempInStack)
					{
						usSglMinTempBankNo = (quint16)(iBankIndex + 1);
						usSglMinTempNoInBank = pBattBank->usSglMinTempNo;
						fSglMinTempInStack =  pBattBank->fSglMinTemp;
					}

					// 清除故障
					if (bNeedClearFault)
					{
						pBattBank->usNeedManualReset = 0;
					}
				}
			}

			usStackCfgInfo = usStackCfgInfo >> 1;
			++iBankIndex;
		}

		// 赋值
        if (m_pBattStack->usStackState != usStackState) //状态有变化
		{
            KG_LOG_INFO(QString("电池堆状态发送了变化:从 0x%1 变为 0x%2.").arg(m_pBattStack->usStackState, 0, 16).arg(usStackState, 0, 16));
			emit notifyPCSStateChanged(m_pBattStack->usStackState, usStackState);

			if (checkRunState(m_pBattStack->usStackState, usStackState))
			{
				m_lstSql << QString("insert into tblLog (startDT, type, context) values ('%1', %2, '%3');").arg(dtStart.toString("yyyy-MM-dd hh:mm:ss")).arg(SYS_LOG_TYPE_RUN).arg(getStateDescrip(m_pBattStack->usStackState, usStackState));
			}

			m_pBattStack->usStackState = usStackState;
		}

		m_pBattStack->usBankStateSum = usBankStateSum;
	
		if (iStackVolNum > 0)
		{
			m_pBattStack->fStackVol = fStackVol / iStackVolNum;
		}
		else
		{
			m_pBattStack->fStackVol = 0;
		}

		m_pBattStack->fStackCur = fStackCur;
		m_pBattStack->fStackPower = m_pBattStack->fStackVol * m_pBattStack->fStackCur / 1000;
		m_pBattStack->fStackInsuRes = fStackInsuRes;

		if (iStackSocNum > 0)
		{
			m_pBattStack->fStackSoc = fStackSoc / iStackSocNum;
		}
		else
		{
			m_pBattStack->fStackSoc = 0;
		}

		if (iStackSohNum > 0)
		{
			m_pBattStack->fStackSoh = fStackSoh / iStackSohNum;
		}
		else
		{
			m_pBattStack->fStackSoh = 0;
		}

		m_pBattStack->fStackChargeEQ = fStackChargeEQ;
		m_pBattStack->fStackDischargeEQ = fStackDischargeEQ;
		m_pBattStack->fStackSglChargeEQ = fStackSglChargeEQ;
        m_pBattStack->fStackSglDischargeEQ = fStackSglDischargeEQ;
		m_pBattStack->fStackSglChargeAh = fStackSglChargeAh;
		m_pBattStack->fStackSglDischargeAh = fStackSglDischargeAh;
	
		m_pBattStack->dblStackChargeEQAdd = dblStackChargeEQAdd;
		m_pBattStack->dblStackDischargeEQAdd = dblStackDischargeEQAdd;
		m_pBattStack->dblStackChargeAhAdd = dblStackChargeAhAdd;
		m_pBattStack->dblStackDischargeAhAdd = dblStackDischargeAhAdd;

		m_pBattStack->usMaxBankSocNo = usBankSocMaxBankNo; //组SOC最大组号                     4
		m_pBattStack->usMinBankSocNo = usBankSocMinBankNo; //组SOC最小组号                     5
		m_pBattStack->usMaxBankVolNo = usBankVolMaxBankNo; //组电压最大组号                    6
		m_pBattStack->usMinBankVolNo = usBankVolMinBankNo; //组电压最小组号                    7
		m_pBattStack->usSglMaxVolBankNo = usSglMaxVolBankNo; //最高单体电压电池组号              8
		m_pBattStack->usSglMaxVolNoInBank = usSglMaxVolNoInBank; //最高电压电池所在组的组内编号      9
		m_pBattStack->usSglMinVolBankNo = usSglMinVolBankNo; //最低单体电压电池组号              10
		m_pBattStack->usSglMinVolNoInBank = usSglMinVolNoInBank; //最低电压电池所在组的组内编号      11
		m_pBattStack->usSglMaxTempBankNo = usSglMaxTempBankNo; //最高电池温度电池组号              12
		m_pBattStack->usSglMaxTempNoInBank = usSglMaxTempNoInBank; //最高电池温度所在组的组内编号      13
		m_pBattStack->usSglMinTempBankNo = usSglMinTempBankNo; //最低电池温度电池组号              14
		m_pBattStack->usSglMinTempNoInBank = usSglMinTempNoInBank; //最低电池温度所在组的组内编号      15
		m_pBattStack->usMaxBankCurNo = usBankCurMaxBankNo; //组电流最大组号                    
		m_pBattStack->usMinBankCurNo = usBankCurMinBankNo; //组电流最小组号                    

		m_pBattStack->fSglVolDiffInStack = fSglMaxVolInStack - fSglMinVolInStack; //单体电压压差极差值	               71
		m_pBattStack->fSglMaxVolInStack = fSglMaxVolInStack; //最高单体电压   		           73
		m_pBattStack->fSglMinVolInStack = fSglMinVolInStack; //最低单体电压                      75
		m_pBattStack->fSglTempDiffInStack = fSglMaxTempInStack - fSglMinTempInStack; //电池温度温差极差值	           77
		m_pBattStack->fSglMaxTempInStack = fSglMaxTempInStack; //最高电池温度                   79
		m_pBattStack->fSglMinTempInStack = fSglMinTempInStack; //最低电池温度                   81
		m_pBattStack->fBankSocDiff = fBankSocMax - fBankSocMin; //组SOC差极差值	               83
		m_pBattStack->fBankSocMax = fBankSocMax; //组SOC最大                      85
		m_pBattStack->fBankSocMin = fBankSocMin; //组SOC最小                      87
		m_pBattStack->fBankVolDiff = fBankVolMax - fBankVolMin; //组电压差极差值	               89
		m_pBattStack->fBankVolMax = fBankVolMax; //组电压最大                     91
		m_pBattStack->fBankVolMin = fBankVolMin; //组电压最小                     93
		m_pBattStack->fBankCurDiff = fBankCurMax - fBankCurMin; //组电流差极差值	             
		m_pBattStack->fBankCurMax = fBankCurMax; //组电流最大                        
		m_pBattStack->fBankCurMin = fBankCurMin; //组电流最小                      

        if (1 == m_pBattStack->usIsolSwitchStrategy || 2 == m_pBattStack->usIsolSwitchStrategy) //隔离开关反馈
		{
			m_pBattStack->usIsolSwitchAggrState = usIsolSwitchAggrState;
		}
		else if (101 == m_pBattStack->usIsolSwitchStrategy)
		{
			if (1 == m_pBattStack->usDI1)
			{
				if (0 == m_pBattStack->usIsolSwitchAggrState)
				{
					m_pBattStack->usIsolSwitchAggrState = 1;

					log2DB(1, dtStart, 1, 1);
				}
			}
			else
			{
				if (1 == m_pBattStack->usIsolSwitchAggrState)
				{
					m_pBattStack->usIsolSwitchAggrState = 0;

					log2DB(1, dtStart, 0, 1);
				}
			}
		}
		else if (102 == m_pBattStack->usIsolSwitchStrategy)
		{
			if (1 == m_pBattStack->usDI2)
			{
				if (0 == m_pBattStack->usIsolSwitchAggrState)
				{
					m_pBattStack->usIsolSwitchAggrState = 1;

					log2DB(1, dtStart, 1, 2);
				}
			}
			else
			{
				if (1 == m_pBattStack->usIsolSwitchAggrState)
				{
					m_pBattStack->usIsolSwitchAggrState = 0;

					log2DB(1, dtStart, 0, 2);
				}
			}
		}
		else if (103 == m_pBattStack->usIsolSwitchStrategy)
		{
			if (1 == m_pBattStack->usDI3)
			{
				if (0 == m_pBattStack->usIsolSwitchAggrState)
				{
					m_pBattStack->usIsolSwitchAggrState = 1;

					log2DB(1, dtStart, 1, 3);
				}
			}
			else
			{
				if (1 == m_pBattStack->usIsolSwitchAggrState)
				{
					m_pBattStack->usIsolSwitchAggrState = 0;

					log2DB(1, dtStart, 0, 3);
				}
			}
		}
		else if (104 == m_pBattStack->usIsolSwitchStrategy)
		{
			if (1 == m_pBattStack->usDI4)
			{
				if (0 == m_pBattStack->usIsolSwitchAggrState)
				{
					m_pBattStack->usIsolSwitchAggrState = 1;

					log2DB(1, dtStart, 1, 4);
				}
			}
			else
			{
				if (1 == m_pBattStack->usIsolSwitchAggrState)
				{
					m_pBattStack->usIsolSwitchAggrState = 0;

					log2DB(1, dtStart, 0, 4);
				}
			}
		}

		// 汇流开关
		if (m_pBattStack->usConfSwitchStrategy > 0)
		{
            if (101 == m_pBattStack->usConfSwitchStrategy) //汇流开关
			{
				if (m_pBattStack->usDI1 > 0)
				{
					m_pBattStack->usConfSwitchState = 1;
				}
				else
				{
					m_pBattStack->usConfSwitchState = 2;
				}
			}
			else if (102 == m_pBattStack->usConfSwitchStrategy) 
			{
				if (m_pBattStack->usDI2 > 0)
				{
					m_pBattStack->usConfSwitchState = 1;
				}
				else
				{
					m_pBattStack->usConfSwitchState = 2;
				}
			}
			else if (103 == m_pBattStack->usConfSwitchStrategy) 
			{
				if (m_pBattStack->usDI3 > 0)
				{
					m_pBattStack->usConfSwitchState = 1;
				}
				else
				{
					m_pBattStack->usConfSwitchState = 2;
				}
			}
			else if (104 == m_pBattStack->usConfSwitchStrategy)
			{
				if (m_pBattStack->usDI4 > 0)
				{
					m_pBattStack->usConfSwitchState = 1;
				}
				else
				{
					m_pBattStack->usConfSwitchState = 2;
				}
			}

			if (m_pBattStack->usLastConfSwitchState != m_pBattStack->usConfSwitchState) 
			{
				m_pBattStack->usLastConfSwitchState = m_pBattStack->usConfSwitchState;

				log2DB(2, dtStart, m_pBattStack->usLastConfSwitchState, 0);
			}
		}
		
		// 降功率
		if (m_pBattStack->usDropPowerEnabled > 0)
		{
			if (0xAAAA == usStackState || 0x5555 == usStackState)
			{
				fBankMaxChargePowerAdd = 0;
				fBankMaxChargeCurrentAdd = 0;
				fBankMaxDischargePowerAdd = 0;
				fBankMaxDischargeCurrentAdd = 0;
			}
			else			
			{
				if (0x1111 == usStackState) 
				{
					fBankMaxChargePowerAdd = 0;
					fBankMaxChargeCurrentAdd = 0;
				}
				else
				{
					// 充电发生降功率
                    if (fBankMaxChargePowerAdd + 0.01 > m_pBattStack->fBankMaxChargePower * m_pBattStack->usBankNumInStack || fBankMaxChargeCurrentAdd + 0.01 > m_pBattStack->fBankMaxChargeCurrent * m_pBattStack->usBankNumInStack) //恢复满功率
					{
						fLastBankMaxChargePowerAdd = fBankMaxChargePowerAdd;
						fLastBankMaxChargeCurrentAdd = fBankMaxChargeCurrentAdd;

						fLastStackMaxChargePower = fBankMaxChargePowerAdd;
						fLastStackMaxChargeCurrent = fBankMaxChargeCurrentAdd;
					}
                    else if (fLastBankMaxChargePowerAdd > (fBankMaxChargePowerAdd + 0.01) || fLastBankMaxChargeCurrentAdd > (fBankMaxChargeCurrentAdd + 0.01)) //充电发生降功率
					{
						fLastBankMaxChargePowerAdd = fBankMaxChargePowerAdd;
						fLastBankMaxChargeCurrentAdd = fBankMaxChargeCurrentAdd;

                        if (m_dtLastChgDropPower.secsTo(dtStart) > 10) //上次充电降功率时间
						{
							fBankMaxChargePowerAdd = qAbs(m_pBattStack->fStackCur) * m_pBattStack->fStackVol * m_pBattStack->fDropPowerRatio * 0.01 / 1000;
							fBankMaxChargeCurrentAdd = qAbs(m_pBattStack->fStackCur) * m_pBattStack->fDropPowerRatio * 0.01;

							if (fLastBankMaxChargePowerAdd < fBankMaxChargePowerAdd)
							{
								fBankMaxChargePowerAdd = fLastBankMaxChargePowerAdd;
							}

							if (fLastBankMaxChargeCurrentAdd < fBankMaxChargeCurrentAdd)
							{
								fBankMaxChargeCurrentAdd = fLastBankMaxChargeCurrentAdd;
							}

							if (m_pBattStack->fStackAllowMaxChargePower > (fBankMaxChargePowerAdd + 0.01))
							{
								m_dtLastChgDropPower = dtStart; //充电降功率

								if (m_pBattStack->usBranNum <= 1)/*并联汇入*/
								{
                                    m_lstSql << QString("insert into tblLog (startDT, type, context) values ('%1', %2, '%3');").arg(dtStart.toString("yyyy-MM-dd hh:mm:ss")).arg(SYS_LOG_TYPE_RUN)
                                        .arg(QString(tr("电池堆[充电降功率]至:%1 kW.")).arg(fBankMaxChargePowerAdd, 0, 'f', 2));

								}
							}

							// 记录上次降功率值
							fLastStackMaxChargePower = fBankMaxChargePowerAdd;
							fLastStackMaxChargeCurrent = fBankMaxChargeCurrentAdd;
						}
						else
						{
							fBankMaxChargePowerAdd = fLastStackMaxChargePower; //维持
							fBankMaxChargeCurrentAdd = fLastStackMaxChargeCurrent;
						}
					}
					else if (fBankMaxChargePowerAdd > (fLastBankMaxChargePowerAdd + m_pBattStack->fBankMaxChargePower * 0.2) || 
                            fBankMaxChargeCurrentAdd > (fLastBankMaxChargeCurrentAdd + m_pBattStack->fBankMaxChargeCurrent * 0.2)) //充电发生恢复
					{
						fLastBankMaxChargePowerAdd = fBankMaxChargePowerAdd;
						fLastBankMaxChargeCurrentAdd = fBankMaxChargeCurrentAdd;

						if (fLastStackMaxChargePower < m_pBattStack->fBankMaxChargePower * m_pBattStack->usBankNumInStack * 0.5)
						{
							fLastStackMaxChargePower = m_pBattStack->fBankMaxChargePower * m_pBattStack->usBankNumInStack * 0.5;
						}

						if (fLastStackMaxChargeCurrent < m_pBattStack->fBankMaxChargeCurrent * m_pBattStack->usBankNumInStack * 0.5)
						{
							fLastStackMaxChargeCurrent = m_pBattStack->fBankMaxChargeCurrent * m_pBattStack->usBankNumInStack * 0.5;
						}
				
						fBankMaxChargePowerAdd = fLastStackMaxChargePower;
						fBankMaxChargeCurrentAdd = fLastStackMaxChargeCurrent;
					}
					else
					{
						fBankMaxChargePowerAdd = fLastStackMaxChargePower; //恢复或维持部分(先前)功率 
						fBankMaxChargeCurrentAdd = fLastStackMaxChargeCurrent;
					}
				}

				if (0x2222 == usStackState)
				{
					fBankMaxDischargePowerAdd = 0;
					fBankMaxDischargeCurrentAdd = 0;
				}
				else
				{
					// 放电发生降功率
                    if (fBankMaxDischargePowerAdd + 0.01 > m_pBattStack->fBankMaxDischargePower * m_pBattStack->usBankNumInStack || fBankMaxDischargeCurrentAdd + 0.01 > m_pBattStack->fBankMaxDischargeCurrent * m_pBattStack->usBankNumInStack) //恢复满功率
					{
						fLastBankMaxDischargePowerAdd = fBankMaxDischargePowerAdd;
						fLastBankMaxDischargeCurrentAdd = fBankMaxDischargeCurrentAdd;

						fLastStackMaxDischargePower = fBankMaxDischargePowerAdd;
						fLastStackMaxDischargeCurrent = fBankMaxDischargeCurrentAdd;
					}
                    else if (fLastBankMaxDischargePowerAdd > (fBankMaxDischargePowerAdd + 0.01) || fLastBankMaxDischargeCurrentAdd > (fBankMaxDischargeCurrentAdd + 0.01)) //放电
					{
						fLastBankMaxDischargePowerAdd = fBankMaxDischargePowerAdd;
						fLastBankMaxDischargeCurrentAdd = fBankMaxDischargeCurrentAdd;

                        if (m_dtLastDhgDropPower.secsTo(dtStart) > 10) //上次放电降功率时间
						{
							fBankMaxDischargePowerAdd = qAbs(m_pBattStack->fStackCur) * m_pBattStack->fStackVol * m_pBattStack->fDropPowerRatio * 0.01 / 1000;
							fBankMaxDischargeCurrentAdd = qAbs(m_pBattStack->fStackCur) * m_pBattStack->fDropPowerRatio * 0.01;

							if (fLastBankMaxDischargePowerAdd < fBankMaxDischargePowerAdd)
							{
								fBankMaxDischargePowerAdd = fLastBankMaxDischargePowerAdd;
							}

							if (fLastBankMaxDischargeCurrentAdd < fBankMaxDischargeCurrentAdd)
							{
								fBankMaxDischargeCurrentAdd = fLastBankMaxDischargeCurrentAdd;
							}

							if (m_pBattStack->fStackAllowMaxDischargePower > (fBankMaxDischargePowerAdd + 0.01))
							{
								m_dtLastDhgDropPower = dtStart; //放电降功率

								if (m_pBattStack->usBranNum <= 1)/*并联汇入*/
								{

                                    m_lstSql << QString("insert into tblLog (startDT, type, context) values ('%1', %2, '%3');").arg(dtStart.toString("yyyy-MM-dd hh:mm:ss")).arg(SYS_LOG_TYPE_RUN)
                                        .arg(QString(tr("电池堆[放电降功率]至:%1 kW.")).arg(fBankMaxDischargePowerAdd, 0, 'f', 2));

								}
							}

							// 记录上次降功率值
							fLastStackMaxDischargePower = fBankMaxDischargePowerAdd;
							fLastStackMaxDischargeCurrent = fBankMaxDischargeCurrentAdd;
						}
						else
						{
							fBankMaxDischargePowerAdd = fLastStackMaxDischargePower; //维持 
							fBankMaxDischargeCurrentAdd = fLastStackMaxDischargeCurrent;
						}
					}
					else if (fBankMaxDischargePowerAdd > (fLastBankMaxDischargePowerAdd + m_pBattStack->fBankMaxDischargePower * 0.2) || 
                        fBankMaxDischargeCurrentAdd > (fLastBankMaxDischargeCurrentAdd + m_pBattStack->fBankMaxDischargeCurrent * 0.2)) //充电发生恢复
					{
						fLastBankMaxDischargePowerAdd = fBankMaxDischargePowerAdd;
						fLastBankMaxDischargeCurrentAdd = fBankMaxDischargeCurrentAdd;

						if (fLastStackMaxDischargePower < m_pBattStack->fBankMaxDischargePower * m_pBattStack->usBankNumInStack * 0.5)
						{
							fLastStackMaxDischargePower = m_pBattStack->fBankMaxDischargePower * m_pBattStack->usBankNumInStack * 0.5;
						}

						if (fLastStackMaxDischargeCurrent < m_pBattStack->fBankMaxDischargeCurrent * m_pBattStack->usBankNumInStack * 0.5)
						{
							fLastStackMaxDischargeCurrent = m_pBattStack->fBankMaxDischargeCurrent * m_pBattStack->usBankNumInStack * 0.5;
						}

						fBankMaxDischargePowerAdd = fLastStackMaxDischargePower;
						fBankMaxDischargeCurrentAdd = fLastStackMaxDischargeCurrent;
					}
					else
					{
						fBankMaxDischargePowerAdd = fLastStackMaxDischargePower; //恢复或维持部分(先前)功率 
						fBankMaxDischargeCurrentAdd = fLastStackMaxDischargeCurrent;
					}
				}

                if (0x1111 == usStackState) //防止降功率计算出错
				{
					if (fBankMaxDischargePowerAdd < m_pBattStack->fBankMaxDischargePower * m_pBattStack->usBankNumInStack * 0.5)
					{
						fBankMaxDischargePowerAdd = m_pBattStack->fBankMaxDischargePower * m_pBattStack->usBankNumInStack * 0.5;
					}

					if (fBankMaxDischargeCurrentAdd < m_pBattStack->fBankMaxDischargeCurrent * m_pBattStack->usBankNumInStack * 0.5)
					{
						fBankMaxDischargeCurrentAdd = m_pBattStack->fBankMaxDischargeCurrent * m_pBattStack->usBankNumInStack * 0.5;
					}
				}
				else if (0x2222 == usStackState)
				{
					if (fBankMaxChargePowerAdd < m_pBattStack->fBankMaxChargePower * m_pBattStack->usBankNumInStack * 0.5)
					{
						fBankMaxChargePowerAdd = m_pBattStack->fBankMaxChargePower * m_pBattStack->usBankNumInStack * 0.5;
					}

					if (fBankMaxChargeCurrentAdd < m_pBattStack->fBankMaxChargeCurrent * m_pBattStack->usBankNumInStack * 0.5)
					{
						fBankMaxChargeCurrentAdd = m_pBattStack->fBankMaxChargeCurrent * m_pBattStack->usBankNumInStack * 0.5;
					}
				}
				else if (0xBBBB == usStackState || 0xCCCC == usStackState)
				{
					if (fBankMaxChargePowerAdd < m_pBattStack->fDropPowerEndCur * m_pBattStack->usBankNumInStack * m_pBattStack->fStackVol * 0.001)
					{
                        fBankMaxChargePowerAdd = m_pBattStack->fDropPowerEndCur * m_pBattStack->usBankNumInStack * m_pBattStack->fStackVol * 0.001;
					}

					if (fBankMaxChargeCurrentAdd < m_pBattStack->fDropPowerEndCur * m_pBattStack->usBankNumInStack)
					{
						fBankMaxChargeCurrentAdd = m_pBattStack->fDropPowerEndCur * m_pBattStack->usBankNumInStack;
					}

					if (fBankMaxDischargePowerAdd < m_pBattStack->fDropPowerEndCur * m_pBattStack->usBankNumInStack * m_pBattStack->fStackVol * 0.001)
					{
						fBankMaxDischargePowerAdd = m_pBattStack->fDropPowerEndCur * m_pBattStack->usBankNumInStack * m_pBattStack->fStackVol * 0.001;
					}

					if (fBankMaxDischargeCurrentAdd < m_pBattStack->fDropPowerEndCur * m_pBattStack->usBankNumInStack)
					{
						fBankMaxDischargeCurrentAdd = m_pBattStack->fDropPowerEndCur * m_pBattStack->usBankNumInStack;
					}
				}
			}
		}
		else
		{
			if (0xAAAA == usStackState || 0x5555 == usStackState)
			{
				fBankMaxChargePowerAdd = 0;
				fBankMaxChargeCurrentAdd = 0;
				fBankMaxDischargePowerAdd = 0;
				fBankMaxDischargeCurrentAdd = 0;
			}
			else if (0x1111 == usStackState) 			
			{
				fBankMaxChargePowerAdd = 0;
				fBankMaxChargeCurrentAdd = 0;
			}
			else if (0x2222 == usStackState)
			{
				fBankMaxDischargePowerAdd = 0;
				fBankMaxDischargeCurrentAdd = 0;
			}
			//fBankMaxChargePowerAdd = 0; //不降功率为最大值
			//fBankMaxChargeCurrentAdd = 0;
			//fBankMaxDischargePowerAdd = 0;
			//fBankMaxDischargeCurrentAdd = 0;
		}
	
		// 赋值
		m_pBattStack->fStackAllowMaxChargePower = fBankMaxChargePowerAdd;
		m_pBattStack->fStackAllowMaxChargeCurrent = fBankMaxChargeCurrentAdd;
        m_pBattStack->fStackAllowMaxDischargePower = fBankMaxDischargePowerAdd;
		m_pBattStack->fStackAllowMaxDischargeCurrent = fBankMaxDischargeCurrentAdd;
		
		if (2 == m_pBattStack->usDCSideConfType)
        {
            // 直流侧汇入类型 0 - 并联汇入  1 - 各组独立  2 - 分支路汇入
			calculateBranch(dtStart);
        }

		// Emerhency Stop
        // processEmerStop(); 不处理急停，由xnbmsio进程来处理

		// Check Client state
		checkClientIdle();

		// Add to DB
		processSql();

		// Check EMS
		checkEMSLink();
	}
}

//计算支路
void CDataTranSrv::calculateBranch(const QDateTime& dtStart)
{
	// some variables
	quint16 usBranCfgInfo = 0;
	int iBankIndex = 0;

    CBattBank* pBattBank = 0;
	CBattBank* pBattBran = 0; //支路
	quint16 usBranState = 0xbbbb; //以等级最低为初始值  0xbbbb - 正常
	quint16 usBankStateSum = 0;

	float fBranVol = 0; //支路总电压         
    int iBranVolNum = 0;
	float fBranCur = 0; //支路总电流 
	float fBranSoc = 0; //支路SOC     
	float fBranInsuRes = 9999; //系统绝缘
	int iBranSocNum = 0;
	float fBranSoh = 0; //支路SOH             
    int iBranSohNum = 0;

    float fBranChargeEQ = 0; //支路可充电量
	float fBranDischargeEQ = 0; //支路可放电量  
	float fBranSglChargeEQ = 0; //支路单次充电电量 
    float fBranSglDischargeEQ = 0; //支路单次放电电量
	float fBranSglChargeAh = 0; //支路单次充电容量 
    float fBranSglDischargeAh = 0; //支路单次放电容量

	double dblBranChargeEQAdd = 0; //支路充电量累加值   
    double dblBranDischargeEQAdd = 0; //支路放电量累加值
	double dblBranChargeAhAdd = 0; //支路充容量累加值   
    double dblBranDischargeAhAdd = 0; //支路放容量累加值

	float fBankMaxChargePowerAdd = 0; //支路最大充电功率
	float fBankMaxDischargePowerAdd = 0; //支路最大放电功率
	float fBankMaxChargeCurrentAdd = 0; //支路最大充电电流
	float fBankMaxDischargeCurrentAdd = 0; //支路最大放电电流

	float fLastBankMaxChargePowerAdd = m_pBattStack->fBankMaxChargePower * m_pBattStack->usMultiConfBankNum; //上次组最大充电功率累加    
	float fLastBankMaxDischargePowerAdd = m_pBattStack->fBankMaxDischargePower * m_pBattStack->usMultiConfBankNum; //上次组最大放电功率累加   
	float fLastBankMaxChargeCurrentAdd = m_pBattStack->fBankMaxChargeCurrent * m_pBattStack->usMultiConfBankNum; //上次组最大充电电流累加   
    float fLastBankMaxDischargeCurrentAdd = m_pBattStack->fBankMaxDischargeCurrent * m_pBattStack->usMultiConfBankNum; //上次组最大放电电流累加

	float fLastBranMaxChargePower = m_pBattStack->fBankMaxChargePower * m_pBattStack->usMultiConfBankNum; //上次支路最大充电功率
	float fLastBranMaxDischargePower = m_pBattStack->fBankMaxDischargePower * m_pBattStack->usMultiConfBankNum; //上次支路最大放电功率   
	float fLastBranMaxChargeCurrent = m_pBattStack->fBankMaxChargeCurrent * m_pBattStack->usMultiConfBankNum; //上次支路最大充电电流   
    float fLastBranMaxDischargeCurrent = m_pBattStack->fBankMaxDischargeCurrent * m_pBattStack->usMultiConfBankNum; //上次支路最大放电电流

	bool bAllBankChg = true; //各组全充电
	bool bAllBankDchg = true; //各组全放电

	quint16 usIsolSwitchAggrState = 1; //隔离开关状态

	// 组间统计
	quint16 usBankSocMaxBankNo = ALARM_BANK_NO;
    quint16 usBankSocMinBankNo = ALARM_BANK_NO;

	quint16 usBankVolMaxBankNo = ALARM_BANK_NO;
	quint16 usBankVolMinBankNo = ALARM_BANK_NO;

	quint16 usSglMaxVolBankNo = ALARM_BANK_NO;
	quint16 usSglMaxVolNoInBank = ALARM_BANK_NO;
    quint16 usSglMinVolBankNo = ALARM_BANK_NO;
	quint16 usSglMinVolNoInBank = ALARM_BANK_NO;

	quint16 usSglMaxTempBankNo = ALARM_BANK_NO;
	quint16 usSglMaxTempNoInBank = ALARM_BANK_NO;
    quint16 usSglMinTempBankNo = ALARM_BANK_NO;
	quint16 usSglMinTempNoInBank = ALARM_BANK_NO;

	float fBankSocMax = 0;
	float fBankSocMin = 0;

	float fBankVolMax = 0;
	float fBankVolMin = 0;

	float fSglMaxVolInBran = 0;
    float fSglMinVolInBran = 0;
	float fSglMaxTempInBran = 0;
	float fSglMinTempInBran = 0;

	for (int iIndex = 0; iIndex < m_pBattStack->usBranNum && iIndex < MAX_BANK_NUM; ++iIndex)
	{
		usBranCfgInfo = m_pBattStack->usBranCfgInfo[iIndex];
		iBankIndex = 0;

		pBattBank = 0;
		pBattBran = m_pRTDB->getBank(iIndex);
		usBranState = 0xbbbb; //以等级最低为初始值  0xbbbb - 正常
		usBankStateSum = 0;

		fBranVol = 0; //支路总电压         
        iBranVolNum = 0;
        fBranCur = 0; //支路总电流
		fBranInsuRes = 9999; //系统绝缘
        fBranSoc = 0; //支路SOC
		iBranSocNum = 0;
        fBranSoh = 0; //支路SOH
        iBranSohNum = 0;

		fBranChargeEQ = 0; //支路可充电量
		fBranDischargeEQ = 0; //支路可放电量
		fBranSglChargeEQ = 0; //支路单次充电电量
		fBranSglDischargeEQ = 0; //支路单次放电电量
		fBranSglChargeAh = 0; //支路单次充电容量 
		fBranSglDischargeAh = 0; //支路单次放电容量

		dblBranChargeEQAdd = 0; //支路充电量累加值
		dblBranDischargeEQAdd = 0; //支路放电量累加值
		dblBranChargeAhAdd = 0; //支路充容量累加值
		dblBranDischargeAhAdd = 0; //支路放容量累加值

		fBankMaxChargePowerAdd = 0; //支路最大充电功率
		fBankMaxDischargePowerAdd = 0; //支路最大放电功率
		fBankMaxChargeCurrentAdd = 0; //支路最大充电电流
		fBankMaxDischargeCurrentAdd = 0; //支路最大放电电流

		bAllBankChg = true; //各组全充电
		bAllBankDchg = true; //各组全放电

		usIsolSwitchAggrState = 1;

		// 组间统计
		usBankSocMaxBankNo = ALARM_BANK_NO;
        usBankSocMinBankNo = ALARM_BANK_NO;
		usBankVolMaxBankNo = ALARM_BANK_NO;
        usBankVolMinBankNo = ALARM_BANK_NO;
		usSglMaxVolBankNo = ALARM_BANK_NO;
		usSglMaxVolNoInBank = ALARM_BANK_NO;
        usSglMinVolBankNo = ALARM_BANK_NO;
		usSglMinVolNoInBank = ALARM_BANK_NO;
		usSglMaxTempBankNo = ALARM_BANK_NO;
		usSglMaxTempNoInBank = ALARM_BANK_NO;
		usSglMinTempBankNo = ALARM_BANK_NO;
		usSglMinTempNoInBank = ALARM_BANK_NO;
		fBankSocMax = 0;
		fBankSocMin = 0;
		fBankVolMax = 0;
		fBankVolMin = 0;
		fSglMaxVolInBran = 0;
		fSglMinVolInBran = 0;
		fSglMaxTempInBran = 0;
		fSglMinTempInBran = 0;

		while(usBranCfgInfo > 0)
		{
			if ((usBranCfgInfo & 0x0001) > 0) //该组参与运算
			{
				if (iBankIndex >= m_pBattStack->usInstallBankNum)
				{
					break;
				}

				pBattBank = m_pRTDB->getBank(iBankIndex);
				if (pBattBank) //单组
				{
					calculateState(usBranState, pBattBank->usBankState);

					// 状态汇总
					if (0x1111 == pBattBank->usBankState && ((pBattBank->usForbidReason & 0x0100) > 0)) //充满导致的禁充
					{
						usBankStateSum |= 0x0001;
					}
					else if (0x2222 == pBattBank->usBankState && ((pBattBank->usForbidReason & 0x0001) > 0)) //放空导致的禁放
					{
						usBankStateSum |= 0x0002;
					}

					// 支路总电压
                    if (pBattBank->fBankVol > BANK_VOL_SAMPLE_INVALID_VALUE_DOWN
                     && pBattBank->fBankVol < BANK_VOL_SAMPLE_INVALID_VALUE_UP)
					{
						fBranVol += pBattBank->fBankVol;
						++iBranVolNum;
					}

                    //支路总电流
                    if (pBattBank->fBankCur > BANK_CUR_SAMPLE_INVALID_VALUE_DOWN
                     && pBattBank->fBankCur < BANK_CUR_SAMPLE_INVALID_VALUE_UP)
                    {
                        fBranCur += pBattBank->fBankCur;
					}

					// 系统绝缘
					if (fBranInsuRes > pBattBank->fBankInsuRes)
					{
						fBranInsuRes = pBattBank->fBankInsuRes;
					}

					if (pBattBank->fBankSoc > -0.001 && pBattBank->fBankSoc < SOC_SAMPLE_INVALID_VALUE_UP)
					{
						fBranSoc += pBattBank->fBankSoc;
						++iBranSocNum;
					}

					if (pBattBank->fBankSoh > 0 && pBattBank->fBankSoh < SOH_SAMPLE_INVALID_VALUE_UP)
					{
						fBranSoh += pBattBank->fBankSoh;
						++iBranSohNum;
					}

					fBranChargeEQ += pBattBank->fBankChargeEQ;
					fBranDischargeEQ += pBattBank->fBankDischargeEQ;
					fBranSglChargeEQ += pBattBank->fBankSglChargeEQ;
					fBranSglDischargeEQ += pBattBank->fBankSglDischargeEQ;
					fBranSglChargeAh += pBattBank->fBankSglChargeAh;
					fBranSglDischargeAh += pBattBank->fBankSglDischargeAh;
					dblBranChargeEQAdd += pBattBank->dblBankChargeEQAdd;
					dblBranDischargeEQAdd += pBattBank->dblBankDischargeEQAdd;
					dblBranChargeAhAdd += pBattBank->dblBankChargeAhAdd;
					dblBranDischargeAhAdd += pBattBank->dblBankDischargeAhAdd;

					fBankMaxChargePowerAdd += pBattBank->fBankAllowMaxChargePower;
					fBankMaxDischargePowerAdd += pBattBank->fBankAllowMaxDischargePower;
					fBankMaxChargeCurrentAdd += pBattBank->fBankAllowMaxChargeCurrent;
					fBankMaxDischargeCurrentAdd += pBattBank->fBankAllowMaxDischargeCurrent;

					if (!(pBattBank->fBankCur < -2)) //各组全放电
					{
						bAllBankDchg = false;
					}

					if (!(pBattBank->fBankCur > 2)) //各组全充电
					{
						bAllBankChg = false;
					}

					if (1 == m_pBattStack->usIsolSwitchStrategy && 0 == pBattBank->usDI3) //隔离开关反馈 BC 的DI3
					{
						usIsolSwitchAggrState = 0;
					}
					else if (2 == m_pBattStack->usIsolSwitchStrategy && 0 == pBattBank->usDI4) //隔离开关反馈 BC 的DI4
					{
						usIsolSwitchAggrState = 0;
					}

					// 组间统计
					if (ALARM_BANK_NO == usBankSocMaxBankNo || pBattBank->fBankSoc > fBankSocMax)
					{
						usBankSocMaxBankNo = (quint16)(iBankIndex + 1);
						fBankSocMax = pBattBank->fBankSoc;
					}

                    if (ALARM_BANK_NO == usBankSocMinBankNo || pBattBank->fBankSoc < fBankSocMin)
					{
						usBankSocMinBankNo = (quint16)(iBankIndex + 1);
						fBankSocMin = pBattBank->fBankSoc;
					}

                    if (ALARM_BANK_NO == usBankVolMaxBankNo || pBattBank->fBankVol > fBankVolMax)
					{
						usBankVolMaxBankNo = (quint16)(iBankIndex + 1);
						fBankVolMax = pBattBank->fBankVol;
					}

                    if (ALARM_BANK_NO == usBankVolMinBankNo || pBattBank->fBankVol < fBankVolMin)
					{
						usBankVolMinBankNo = (quint16)(iBankIndex + 1);
						fBankVolMin = pBattBank->fBankVol;
					}

					if (ALARM_BANK_NO == usSglMaxVolBankNo || pBattBank->fSglMaxVol > fSglMaxVolInBran)
					{
						usSglMaxVolBankNo = (quint16)(iBankIndex + 1);
						usSglMaxVolNoInBank = pBattBank->usSglMaxVolNo;
						fSglMaxVolInBran =  pBattBank->fSglMaxVol;
					}

					if (ALARM_BANK_NO == usSglMinVolBankNo || pBattBank->fSglMinVol < fSglMinVolInBran)
					{
						usSglMinVolBankNo = (quint16)(iBankIndex + 1);
						usSglMinVolNoInBank = pBattBank->usSglMinVolNo;
						fSglMinVolInBran =  pBattBank->fSglMinVol;
					}

					if (ALARM_BANK_NO == usSglMaxTempBankNo || pBattBank->fSglMaxTemp > fSglMaxTempInBran)
					{
						usSglMaxTempBankNo = (quint16)(iBankIndex + 1);
						usSglMaxTempNoInBank = pBattBank->usSglMaxTempNo;
						fSglMaxTempInBran =  pBattBank->fSglMaxTemp;
					}

					if (ALARM_BANK_NO == usSglMinTempBankNo || pBattBank->fSglMinTemp < fSglMinTempInBran)
					{
						usSglMinTempBankNo = (quint16)(iBankIndex + 1);
						usSglMinTempNoInBank = pBattBank->usSglMinTempNo;
						fSglMinTempInBran =  pBattBank->fSglMinTemp;
					}
				}
			}

			usBranCfgInfo = usBranCfgInfo >> 1;
			++iBankIndex;
		}

		// 赋值
		if (pBattBran)
		{
			if (pBattBran->usBranState != usBranState) //状态有变化
			{
                KG_LOG_INFO(QString("支路状态发生了变化:从 0x%1 变为了 0x%2.").arg(pBattBran->usBranState, 0, 16).arg(usBranState, 0, 16));
				emit notifyPCSStateChanged(pBattBran->usBranState, usBranState);

				if (checkRunState(pBattBran->usBranState, usBranState))
				{
                    int iBranNo = GetBranNo(iBankIndex);
                    m_lstSql << QString(("insert into tblLog (startDT, type, context) values ('%1', %2, '支路%3 %4');"))
                                    .arg(dtStart.toString("yyyy-MM-dd hh:mm:ss"))
                                    .arg(SYS_LOG_TYPE_RUN)
                                    .arg(iBranNo)
                                    .arg(getStateDescrip(pBattBran->usBranState, usBranState));
				}

				pBattBran->usBranState = usBranState;
			}

			pBattBran->usBankStateSum = usBankStateSum;

            //支路电压
			if (iBranVolNum > 0)
			{
				pBattBran->fBranVol = fBranVol / iBranVolNum;
			}
			else
			{
				pBattBran->fBranVol = 0;
			}

            //支路电流
			pBattBran->fBranCur = fBranCur;
            //支路有功功率
			pBattBran->fBranPower = pBattBran->fBranVol * pBattBran->fBranCur / 1000;
            //支路内阻
			pBattBran->fBranInsuRes = fBranInsuRes;

            //支路SOC
			if (iBranSocNum > 0)
			{
				pBattBran->fBranSoc = fBranSoc / iBranSocNum;
			}
			else
			{
				pBattBran->fBranSoc = 0;
			}

            //支路SOH
			if (iBranSohNum > 0)
			{
				pBattBran->fBranSoh = fBranSoh / iBranSohNum;
			}
			else
			{
				pBattBran->fBranSoh = 0;
			}

			pBattBran->fBranChargeEQ = fBranChargeEQ;
			pBattBran->fBranDischargeEQ = fBranDischargeEQ;
			pBattBran->fBranSglChargeEQ = fBranSglChargeEQ;
            pBattBran->fBranSglDischargeEQ = fBranSglDischargeEQ;
			pBattBran->fBranSglChargeAh = fBranSglChargeAh;
			pBattBran->fBranSglDischargeAh = fBranSglDischargeAh;

			pBattBran->dblBranChargeEQAdd = dblBranChargeEQAdd;
            pBattBran->dblBranDischargeEQAdd = dblBranDischargeEQAdd;
			pBattBran->dblBranChargeAhAdd = dblBranChargeAhAdd;
			pBattBran->dblBranDischargeAhAdd = dblBranDischargeAhAdd;

            pBattBran->usMaxBankSocNoInBran = usBankSocMaxBankNo;
			pBattBran->usMinBankSocNoInBran = usBankSocMinBankNo;
			pBattBran->usMaxBankVolNoInBran = usBankVolMaxBankNo;
			pBattBran->usMinBankVolNoInBran = usBankVolMinBankNo;
            pBattBran->usSglMaxVolBankNoInBran = usSglMaxVolBankNo;
            pBattBran->usSglMaxVolNoInBankInBran = usSglMaxVolNoInBank;
            pBattBran->usSglMinVolBankNoInBran = usSglMinVolBankNo;
            pBattBran->usSglMinVolNoInBankInBran = usSglMinVolNoInBank;
			pBattBran->usSglMaxTempBankNoInBran = usSglMaxTempBankNo;
			pBattBran->usSglMaxTempNoInBankInBran = usSglMaxTempNoInBank;
			pBattBran->usSglMinTempBankNoInBran = usSglMinTempBankNo;
            pBattBran->usSglMinTempNoInBankInBran = usSglMinTempNoInBank;

            pBattBran->fSglVolDiffInBran = fSglMaxVolInBran - fSglMinVolInBran;
			pBattBran->fSglMaxVolInBran = fSglMaxVolInBran;
            pBattBran->fSglMinVolInBran = fSglMinVolInBran;
			pBattBran->fSglTempDiffInBran = fSglMaxTempInBran - fSglMinTempInBran;
			pBattBran->fSglMaxTempInBran = fSglMaxTempInBran;
			pBattBran->fSglMinTempInBran = fSglMinTempInBran;
			pBattBran->fBankSocDiffInBran = fBankSocMax - fBankSocMin;
            pBattBran->fBankSocMaxInBran = fBankSocMax;
            pBattBran->fBankSocMinInBran = fBankSocMin;
            pBattBran->fBankVolDiffInBran = fBankVolMax - fBankVolMin;
			pBattBran->fBankVolMaxInBran = fBankVolMax;
			pBattBran->fBankVolMinInBran = fBankVolMin;

			if (1 == m_pBattStack->usIsolSwitchStrategy || 2 == m_pBattStack->usIsolSwitchStrategy) //隔离开关反馈
			{
				pBattBran->usIsolSwitchAggrState = usIsolSwitchAggrState;
			}

			// 降功率
			if (m_pBattStack->usDropPowerEnabled > 0)
			{
				if (0xAAAA == usBranState || 0x5555 == usBranState)
				{
					fBankMaxChargePowerAdd = 0;
					fBankMaxChargeCurrentAdd = 0;
					fBankMaxDischargePowerAdd = 0;
					fBankMaxDischargeCurrentAdd = 0;
				}
				else			
				{
					if (0x1111 == usBranState) 
					{
						fBankMaxChargePowerAdd = 0;
						fBankMaxChargeCurrentAdd = 0;
					}
					else
					{
						// 充电发生降功率
                        if (fBankMaxChargePowerAdd + 0.01 > m_pBattStack->fBankMaxChargePower * m_pBattStack->usMultiConfBankNum
                         || fBankMaxChargeCurrentAdd + 0.01 > m_pBattStack->fBankMaxChargeCurrent * m_pBattStack->usMultiConfBankNum)
						{
                            //恢复满功率
							fLastBankMaxChargePowerAdd = fBankMaxChargePowerAdd;
							fLastBankMaxChargeCurrentAdd = fBankMaxChargeCurrentAdd;

							fLastBranMaxChargePower = fBankMaxChargePowerAdd;
                            fLastBranMaxChargeCurrent = fBankMaxChargeCurrentAdd;
						}
                        else if (fLastBankMaxChargePowerAdd > (fBankMaxChargePowerAdd + 0.01)
                              || fLastBankMaxChargeCurrentAdd > (fBankMaxChargeCurrentAdd + 0.01))
						{
                            //充电发生降功率
							fLastBankMaxChargePowerAdd = fBankMaxChargePowerAdd;
							fLastBankMaxChargeCurrentAdd = fBankMaxChargeCurrentAdd;

                            QDateTime dtLastChgDropPower = pBattBran->GetTimeBranChgDropPower();

							if (qAbs(dtLastChgDropPower.secsTo(dtStart) > 10)) //上次充电降功率时间
							{
                                fBankMaxChargePowerAdd = qAbs(pBattBran->fBranCur) * pBattBran->fBranVol * m_pBattStack->fDropPowerRatio * 0.01 / 1000;
								fBankMaxChargeCurrentAdd = qAbs(pBattBran->fBranCur) * m_pBattStack->fDropPowerRatio * 0.01;

								if (fLastBankMaxChargePowerAdd < fBankMaxChargePowerAdd)
								{
									fBankMaxChargePowerAdd = fLastBankMaxChargePowerAdd;
								}

								if (fLastBankMaxChargeCurrentAdd < fBankMaxChargeCurrentAdd)
								{
									fBankMaxChargeCurrentAdd = fLastBankMaxChargeCurrentAdd;
								}

								if (pBattBran->fBranAllowMaxChargePower > (fBankMaxChargePowerAdd + 0.01))
								{
                                    //支路充电降功率时间
                                    pBattBran->SetTimeBranChgDropPower(dtStart);
                                    int iBranNo = GetBranNo(iBankIndex);
                                    m_lstSql << QString("insert into tblLog (startDT, type, context) values ('%1', %2, '%3');")
                                                    .arg(dtStart.toString("yyyy-MM-dd hh:mm:ss"))
                                                    .arg(SYS_LOG_TYPE_RUN)
                                                    .arg(QString(tr("支路%1[充电降功率]至:%2 kW."))
                                                    .arg(iBranNo)
                                                    .arg(fBankMaxChargePowerAdd, 0, 'f', 2));
								}

								// 记录上次降功率值
								fLastBranMaxChargePower = fBankMaxChargePowerAdd;
								fLastBranMaxChargeCurrent = fBankMaxChargeCurrentAdd;
							}
							else
							{
								fBankMaxChargePowerAdd = fLastBranMaxChargePower; //维持
								fBankMaxChargeCurrentAdd = fLastBranMaxChargeCurrent;
							}
						}
                        else if (fBankMaxChargePowerAdd > (fLastBankMaxChargePowerAdd + m_pBattStack->fBankMaxChargePower * 0.2)
                              || fBankMaxChargeCurrentAdd > (fLastBankMaxChargeCurrentAdd + m_pBattStack->fBankMaxChargeCurrent * 0.2))
						{
                            //充电发生恢复
							fLastBankMaxChargePowerAdd = fBankMaxChargePowerAdd;
							fLastBankMaxChargeCurrentAdd = fBankMaxChargeCurrentAdd;

							if (fLastBranMaxChargePower < m_pBattStack->fBankMaxChargePower * m_pBattStack->usMultiConfBankNum * 0.5)
							{
								fLastBranMaxChargePower = m_pBattStack->fBankMaxChargePower * m_pBattStack->usMultiConfBankNum * 0.5;
							}

							if (fLastBranMaxChargeCurrent < m_pBattStack->fBankMaxChargeCurrent * m_pBattStack->usMultiConfBankNum * 0.5)
							{
								fLastBranMaxChargeCurrent = m_pBattStack->fBankMaxChargeCurrent * m_pBattStack->usMultiConfBankNum * 0.5;
							}

                            fBankMaxChargePowerAdd = fLastBranMaxChargePower;
							fBankMaxChargeCurrentAdd = fLastBranMaxChargeCurrent;
						}
						else
						{
                            //恢复或维持部分(先前)功率
                            fBankMaxChargePowerAdd = fLastBranMaxChargePower;
							fBankMaxChargeCurrentAdd = fLastBranMaxChargeCurrent;
						}
					}

					if (0x2222 == usBranState)
					{
						fBankMaxDischargePowerAdd = 0;
						fBankMaxDischargeCurrentAdd = 0;
					}
					else
					{
						// 放电发生降功率
                        if (fBankMaxDischargePowerAdd + 0.01 > m_pBattStack->fBankMaxDischargePower * m_pBattStack->usMultiConfBankNum
                         || fBankMaxDischargeCurrentAdd + 0.01 > m_pBattStack->fBankMaxDischargeCurrent * m_pBattStack->usMultiConfBankNum)
						{
                            //恢复满功率
							fLastBankMaxDischargePowerAdd = fBankMaxDischargePowerAdd;
							fLastBankMaxDischargeCurrentAdd = fBankMaxDischargeCurrentAdd;

							fLastBranMaxDischargePower = fBankMaxDischargePowerAdd;
							fLastBranMaxDischargeCurrent = fBankMaxDischargeCurrentAdd;
						}
                        else if (fLastBankMaxDischargePowerAdd > (fBankMaxDischargePowerAdd + 0.01)
                              || fLastBankMaxDischargeCurrentAdd > (fBankMaxDischargeCurrentAdd + 0.01))
                        {
                            //放电
							fLastBankMaxDischargePowerAdd = fBankMaxDischargePowerAdd;
							fLastBankMaxDischargeCurrentAdd = fBankMaxDischargeCurrentAdd;

                            QDateTime dtLastDchgDropPower = pBattBran->GetTimeBranDchgDropPower();

							if (qAbs(dtLastDchgDropPower.secsTo(dtStart)) > 10) //上次放电降功率时间
							{
								fBankMaxDischargePowerAdd = qAbs(pBattBran->fBranCur) * pBattBran->fBranVol * m_pBattStack->fDropPowerRatio * 0.01 / 1000;
								fBankMaxDischargeCurrentAdd = qAbs(pBattBran->fBranCur) * m_pBattStack->fDropPowerRatio * 0.01;

								if (fLastBankMaxDischargePowerAdd < fBankMaxDischargePowerAdd)
								{
									fBankMaxDischargePowerAdd = fLastBankMaxDischargePowerAdd;
								}

								if (fLastBankMaxDischargeCurrentAdd < fBankMaxDischargeCurrentAdd)
								{
									fBankMaxDischargeCurrentAdd = fLastBankMaxDischargeCurrentAdd;
								}

								if (pBattBran->fBranAllowMaxDischargePower > (fBankMaxDischargePowerAdd + 0.01))
								{
                                    //支路充电降功率时间
                                    pBattBran->SetTimeBranDchgDropPower(dtStart);
                                    int iBranNo = GetBranNo(iBankIndex);
                                    /*if (1 == m_pBattStack->usLang)
									{
										m_lstSql << QString("insert into tblLog (startDT, type, context) values ('%1', %2, '%3');").arg(dtStart.toString("yyyy-MM-dd hh:mm:ss")).arg(SYS_LOG_TYPE_RUN)
                                            .arg(QString(("Branch%1 [Reduce_Discharge_Power] to:%2 kW.")).arg(iBranNo).arg(fBankMaxDischargePowerAdd, 0, 'f', 2));
									}
                                    else*/
									{
                                        m_lstSql << QString("insert into tblLog (startDT, type, context) values ('%1', %2, '%3');")
                                                        .arg(dtStart.toString("yyyy-MM-dd hh:mm:ss"))
                                                        .arg(SYS_LOG_TYPE_RUN)
                                                        .arg(QString(tr("支路%1[放电降功率]至:%2 kW."))
                                                        .arg(iBranNo)
                                                        .arg(fBankMaxDischargePowerAdd, 0, 'f', 2));
									}
								}

								// 记录上次降功率值
								fLastBranMaxDischargePower = fBankMaxDischargePowerAdd;
								fLastBranMaxDischargeCurrent = fBankMaxDischargeCurrentAdd;
							}
							else
							{
								fBankMaxDischargePowerAdd = fLastBranMaxDischargePower; //维持 
								fBankMaxDischargeCurrentAdd = fLastBranMaxDischargeCurrent;
							}
						}
                        else if (fBankMaxDischargePowerAdd > (fLastBankMaxDischargePowerAdd + m_pBattStack->fBankMaxDischargePower * 0.2)
                             || fBankMaxDischargeCurrentAdd > (fLastBankMaxDischargeCurrentAdd + m_pBattStack->fBankMaxDischargeCurrent * 0.2))
						{
                            //充电发生恢复
							fLastBankMaxDischargePowerAdd = fBankMaxDischargePowerAdd;
							fLastBankMaxDischargeCurrentAdd = fBankMaxDischargeCurrentAdd;

							if (fLastBranMaxDischargePower < m_pBattStack->fBankMaxDischargePower * m_pBattStack->usMultiConfBankNum * 0.5)
							{
								fLastBranMaxDischargePower = m_pBattStack->fBankMaxDischargePower * m_pBattStack->usMultiConfBankNum * 0.5;
							}

							if (fLastBranMaxDischargeCurrent < m_pBattStack->fBankMaxDischargeCurrent * m_pBattStack->usMultiConfBankNum * 0.5)
							{
								fLastBranMaxDischargeCurrent = m_pBattStack->fBankMaxDischargeCurrent * m_pBattStack->usMultiConfBankNum * 0.5;
							}

							fBankMaxDischargePowerAdd = fLastBranMaxDischargePower;
                            fBankMaxDischargeCurrentAdd = fLastBranMaxDischargeCurrent;
						}
						else
						{
                            //恢复或维持部分(先前)功率
                            fBankMaxDischargePowerAdd = fLastBranMaxDischargePower;
							fBankMaxDischargeCurrentAdd = fLastBranMaxDischargeCurrent;
						}
					}

					if (0x1111 == usBranState) //防止降功率计算出错
					{
						if (fBankMaxDischargePowerAdd < m_pBattStack->fBankMaxDischargePower * m_pBattStack->usMultiConfBankNum * 0.5)
						{
							fBankMaxDischargePowerAdd = m_pBattStack->fBankMaxDischargePower * m_pBattStack->usMultiConfBankNum * 0.5;
						}

						if (fBankMaxDischargeCurrentAdd < m_pBattStack->fBankMaxDischargeCurrent * m_pBattStack->usMultiConfBankNum * 0.5)
						{
							fBankMaxDischargeCurrentAdd = m_pBattStack->fBankMaxDischargeCurrent * m_pBattStack->usMultiConfBankNum * 0.5;
						}
					}
					else if (0x2222 == usBranState)
					{
						if (fBankMaxChargePowerAdd < m_pBattStack->fBankMaxChargePower * m_pBattStack->usMultiConfBankNum * 0.5)
						{
							fBankMaxChargePowerAdd = m_pBattStack->fBankMaxChargePower * m_pBattStack->usMultiConfBankNum * 0.5;
						}

						if (fBankMaxChargeCurrentAdd < m_pBattStack->fBankMaxChargeCurrent * m_pBattStack->usMultiConfBankNum * 0.5)
						{
							fBankMaxChargeCurrentAdd = m_pBattStack->fBankMaxChargeCurrent * m_pBattStack->usMultiConfBankNum * 0.5;
						}
					}
					else if (0xBBBB == usBranState || 0xCCCC == usBranState)
					{
						if (fBankMaxChargePowerAdd < m_pBattStack->fDropPowerEndCur * m_pBattStack->usMultiConfBankNum * pBattBran->fBranVol * 0.001)
						{
                            fBankMaxChargePowerAdd = m_pBattStack->fDropPowerEndCur * m_pBattStack->usMultiConfBankNum * pBattBran->fBranVol * 0.001;
						}

						if (fBankMaxChargeCurrentAdd < m_pBattStack->fDropPowerEndCur * m_pBattStack->usMultiConfBankNum)
						{
							fBankMaxChargeCurrentAdd = m_pBattStack->fDropPowerEndCur * m_pBattStack->usMultiConfBankNum;
						}

						if (fBankMaxDischargePowerAdd < m_pBattStack->fDropPowerEndCur * m_pBattStack->usMultiConfBankNum * pBattBran->fBranVol * 0.001)
						{
							fBankMaxDischargePowerAdd = m_pBattStack->fDropPowerEndCur * m_pBattStack->usMultiConfBankNum * pBattBran->fBranVol * 0.001;
						}

						if (fBankMaxDischargeCurrentAdd < m_pBattStack->fDropPowerEndCur * m_pBattStack->usMultiConfBankNum)
						{
							fBankMaxDischargeCurrentAdd = m_pBattStack->fDropPowerEndCur * m_pBattStack->usMultiConfBankNum;
						}
					}
				}
			}
			else
			{
				if (0xAAAA == usBranState || 0x5555 == usBranState)
				{
					fBankMaxChargePowerAdd = 0;
					fBankMaxChargeCurrentAdd = 0;
					fBankMaxDischargePowerAdd = 0;
					fBankMaxDischargeCurrentAdd = 0;
				}
				else if (0x1111 == usBranState) 			
				{
					fBankMaxChargePowerAdd = 0;
					fBankMaxChargeCurrentAdd = 0;
				}
				else if (0x2222 == usBranState)
				{
					fBankMaxDischargePowerAdd = 0;
					fBankMaxDischargeCurrentAdd = 0;
				}
			}

			// 赋值
			pBattBran->fBranAllowMaxChargePower = fBankMaxChargePowerAdd;
			pBattBran->fBranAllowMaxChargeCurrent = fBankMaxChargeCurrentAdd;
			pBattBran->fBranAllowMaxDischargePower = fBankMaxDischargePowerAdd;
			pBattBran->fBranAllowMaxDischargeCurrent = fBankMaxDischargeCurrentAdd;
		}
	}
}
// 0xAAAA 故障	5
// 0x5555 告警	4
// 0x2222 禁放	3
// 0x1111 禁充	2
// 0xBBBB 正常	1
void CDataTranSrv::calculateState(quint16& usStackState, quint16 usNewBattState)
{
	switch (usNewBattState)
	{
	case 0xAAAA:
		usStackState = usNewBattState;
		break;
	case 0x5555:
		if (0xAAAA != usStackState)
		{
			usStackState = usNewBattState;
		}
		break;
	case 0x2222:
		if (!(0xAAAA == usStackState || 0x5555 == usStackState)) 
		{
			if (0x1111 == usStackState)
			{
				usStackState = 0x5555;
			}
			else
			{
				usStackState = usNewBattState;
			}
		}
		break;
	case 0x1111:
		if (!(0xAAAA == usStackState || 0x5555 == usStackState)) 
		{
			if (0x2222 == usStackState)
			{
				usStackState = 0x5555;
			}
			else
			{
				usStackState = usNewBattState;
			}
		}
		break;
	case 0xCCCC:
		if (0xAAAA != usStackState && 0x5555 != usStackState && 0x2222 != usStackState && 0x1111 != usStackState)
		{
			usStackState = usNewBattState;
		}
		break;
	case 0xBBBB:
		if (0xAAAA != usStackState && 0x5555 != usStackState && 0x2222 != usStackState && 0x1111 != usStackState && 0xCCCC != usStackState)
		{
			usStackState = usNewBattState;
		}
		break;
	default:
		break;
	}
}

// 检查客户端是否长时间处于空闲状态
// >= 设定的值 强制关闭连接
// 每秒检查一次
void CDataTranSrv::checkClientIdle()
{
	STcpClient* pTcpClient = 0;
	for (int i = 0; i < MAX_MODBUS_TCP_CLIENT_NUM; ++i)
	{
		pTcpClient = m_plstTcpClient->at(i);
		if (pTcpClient && pTcpClient->pTcpSocket)
		{
			++pTcpClient->iIdleTimeCount;

			if (pTcpClient->iIdleTimeCount > m_iIdleTime)
			{
                KG_LOG_INFO(QString("tcp客户端(%1)在%2s内已没有收发数据, 将主动断开此客户端的连接...").arg(i + 1).arg(m_iIdleTime));

				emit tcpCliDisconnectedSgl(i);
				//tcpCli1Disconnected();
			}
		}
	}
}

// 增加信号槽防止出现不在同一线程的断言
void CDataTranSrv::tcpCliDisconnectedSlot(int iCliIndex)
{
	if (0 == iCliIndex)
	{
		tcpCli1Disconnected();
	}
	else if (1 == iCliIndex)
	{
		tcpCli2Disconnected();
	}
	else if (2 == iCliIndex)
	{
		tcpCli3Disconnected();
	}
	else if (3 == iCliIndex)
	{
		tcpCli4Disconnected();
	}
	else if (4 == iCliIndex)
	{
		tcpCli5Disconnected();
	}
	else if (5 == iCliIndex)
	{
		tcpCli6Disconnected();
	}
	else if (6 == iCliIndex)
	{
		tcpCli7Disconnected();
	}
	else if (7 == iCliIndex)
	{
		tcpCli8Disconnected();
	}
	else if (8 == iCliIndex)
	{
		tcpCli9Disconnected();
	}
	else if (9 == iCliIndex)
	{
		tcpCli10Disconnected();
	}
	else if (10 == iCliIndex)
	{
		tcpCli11Disconnected();
	}
	else if (11 == iCliIndex)
	{
		tcpCli12Disconnected();
	}
	else if (12 == iCliIndex)
	{
		tcpCli13Disconnected();
	}
	else if (13 == iCliIndex)
	{
		tcpCli14Disconnected();
	}
	else if (14 == iCliIndex)
	{
		tcpCli15Disconnected();
	}
	else if (15 == iCliIndex)
	{
		tcpCli16Disconnected();
	}
	else if (16 == iCliIndex)
	{
		tcpCli17Disconnected();
	}
}

QString CDataTranSrv::getStateDescrip(quint16 usOldState, quint16 usCurState)
{
	QString strDescrip = "";


    strDescrip = tr("运行状态改变(由 ") + getStackState(usOldState) + tr(" 转变为 ") + getStackState(usCurState) + ").";

	return strDescrip;
}

QString CDataTranSrv::getStackState(quint16 usState)
{
    QString strDescrip = tr("未知");

    if (1 == usState)
    {
        strDescrip = tr("开路");
    }
    else if (2 == usState)
    {
        strDescrip = tr("待机");
    }
    else if (3 == usState)
    {
        strDescrip = tr("充电");
    }
    else if (4 == usState)
    {
        strDescrip = tr("放电");
    }
    else if (0x1111 == usState)
    {
        strDescrip = tr("禁充");
    }
    else if (0x2222 == usState)
    {
        strDescrip = tr("禁放");
    }
    else if (0x5555 == usState)
    {
        strDescrip = tr("告警");
    }
    else if (0xAAAA == usState)
    {
        strDescrip = tr("故障");
    }
    else if (0xBBBB == usState)
    {
        strDescrip = tr("正常");
    }
    else if (0xCCCC == usState)
    {
        strDescrip = tr("预警");
    }

	return strDescrip;
}

// PCS 状态是否存在未知
bool CDataTranSrv::checkRunState(quint16 usOldState, quint16 usCurState)
{
	if (0x1111 == usOldState || 0x2222 == usOldState || 0x5555 == usOldState || 0xAAAA == usOldState || 0xBBBB == usOldState|| 0xCCCC == usOldState)
	{
		if (0x1111 == usCurState || 0x2222 == usCurState || 0x5555 == usCurState || 0xAAAA == usCurState || 0xBBBB == usCurState|| 0xCCCC == usCurState)
		{
			return true;
		}
	}

	return false;
}

void CDataTranSrv::processSql()
{
	if (m_lstSql.size() <= 0)
	{
		return;
	}

	QSqlDatabase db = QSqlDatabase::database();
	QSqlQuery query;

	db.transaction();
	for (int i = 0; i < m_lstSql.size(); ++i)
	{
		query.exec(m_lstSql.at(i));
		query.clear();
	}
	db.commit(); 

	m_lstSql.clear();
	query.clear();
}


void CDataTranSrv::initAlarmCache()
{
	for (int i = 0; i < MAX_BANK_NUM; ++i)
	{
		m_pAlmCacheSem[i] = new QSystemSemaphore(QString("KGDZ_BAMS_SEM%1").arg(i + 1), 1, QSystemSemaphore::Open);
	}
}


void CDataTranSrv::log2DB(int iLogType, const QDateTime& dtStart, quint16 usVal1, quint16 usVal2)
{
	if (1 == iLogType) //隔离开关
	{

        if (0 == usVal1)
        {
            m_lstSql << QString("insert into tblLog (startDT, type, context) values ('%1', %2, '%3');").arg(dtStart.toString("yyyy-MM-dd hh:mm:ss")).arg(SYS_LOG_TYPE_RUN).arg(QString(tr("隔离开关断开(接BAMS DI%1).")).arg(usVal2));
        }
        else
        {
            m_lstSql << QString("insert into tblLog (startDT, type, context) values ('%1', %2, '%3');").arg(dtStart.toString("yyyy-MM-dd hh:mm:ss")).arg(SYS_LOG_TYPE_RUN).arg(QString(tr("隔离开关闭合(接BAMS DI%1).")).arg(usVal2));
        }

	}
	else if (2 == iLogType) //汇流开关
	{

        if (2 == usVal1)
        {
            m_lstSql << QString("insert into tblLog (startDT, type, context) values ('%1', %2, '%3');").arg(dtStart.toString("yyyy-MM-dd hh:mm:ss")).arg(SYS_LOG_TYPE_RUN).arg(QString(tr("汇流开关断开.")));
        }
        else if (1 == usVal1)
        {
            m_lstSql << QString("insert into tblLog (startDT, type, context) values ('%1', %2, '%3');").arg(dtStart.toString("yyyy-MM-dd hh:mm:ss")).arg(SYS_LOG_TYPE_RUN).arg(QString(tr("汇流开关闭合.")));
        }

	}
}

void CDataTranSrv::processEmerStop()
{
	if (0 == m_pBattStack->usEmerStopStrategy)
	{
        //紧急停机策略     1-BC 2-BA 3-ExtIO
		return;
	}

	CBattBank* pBattBank = m_pRTDB->getBank(0);

	if (1 == m_pBattStack->usEmerStopStrategy) //组1BC(DI2) 常开
	{
		if (pBattBank)
		{
			if (pBattBank->usDI2 > 0)
			{
				m_pBattStack->usEmerStopState = 1; //1 - 告警 
			}
			else
			{
				m_pBattStack->usEmerStopState = 2; //2 - 正常
			}
		}
	}
    else if (11 == m_pBattStack->usEmerStopStrategy) //组1BC(DI2) 常闭
	{
		if (pBattBank)
		{
			if (0 == pBattBank->usDI2)
			{
				m_pBattStack->usEmerStopState = 1; //1 - 告警 
			}
			else
			{
				m_pBattStack->usEmerStopState = 2; //2 - 正常
			}
		}
	}
	else if (2 == m_pBattStack->usEmerStopStrategy) // 组1BC(DI3) 常开
	{
		if (pBattBank)
		{
			if (pBattBank->usDI3 > 0)
			{
				m_pBattStack->usEmerStopState = 1; //1 - 告警 
			}
			else
			{
				m_pBattStack->usEmerStopState = 2; //2 - 正常
			}
		}
	}
    else if (12 == m_pBattStack->usEmerStopStrategy) //组1BC(DI3) 常闭
	{
		if (pBattBank)
		{
			if (0 == pBattBank->usDI3)
			{
				m_pBattStack->usEmerStopState = 1; //1 - 告警 
			}
			else
			{
				m_pBattStack->usEmerStopState = 2; //2 - 正常
			}
		}
	}
	else if (3 == m_pBattStack->usEmerStopStrategy) // 组1BC(DI4) 常开
	{
		if (pBattBank)
		{
			if (pBattBank->usDI4 > 0)
			{
				m_pBattStack->usEmerStopState = 1; //1 - 告警 
			}
			else
			{
				m_pBattStack->usEmerStopState = 2; //2 - 正常
			}
		}
	}
    else if (13 == m_pBattStack->usEmerStopStrategy) //组1BC(DI4) 常闭
	{
		if (pBattBank)
		{
			if (0 == pBattBank->usDI4)
			{
				m_pBattStack->usEmerStopState = 1; //1 - 告警 
			}
			else
			{
				m_pBattStack->usEmerStopState = 2; //2 - 正常
			}
		}
	}
	else if (101 == m_pBattStack->usEmerStopStrategy) //紧急停机 - 断开告警
	{
		if (0 == m_pBattStack->usDI1)
		{
			m_pBattStack->usEmerStopState = 1; //1 - 告警 
		}
		else
		{
			m_pBattStack->usEmerStopState = 2; //2 - 正常
		}
	}
    else if (111 == m_pBattStack->usEmerStopStrategy) //紧急停机 - 闭合告警
	{
		if (m_pBattStack->usDI1 > 0)
		{
			m_pBattStack->usEmerStopState = 1; //1 - 告警 
		}
		else
		{
			m_pBattStack->usEmerStopState = 2; //2 - 正常
		}
	}
	else if (102 == m_pBattStack->usEmerStopStrategy) //紧急停机 - 断开告警
	{
		if (0 == m_pBattStack->usDI2)
		{
			m_pBattStack->usEmerStopState = 1; //1 - 告警 
		}
		else
		{
			m_pBattStack->usEmerStopState = 2; //2 - 正常
		}
	}
    else if (112 == m_pBattStack->usEmerStopStrategy) //紧急停机 - 闭合告警
	{
		if (m_pBattStack->usDI2 > 0)
		{
			m_pBattStack->usEmerStopState = 1; //1 - 告警 
		}
		else
		{
			m_pBattStack->usEmerStopState = 2; //2 - 正常
		}
	}
	else if (103 == m_pBattStack->usEmerStopStrategy) //紧急停机 - 断开告警
	{
		if (0 == m_pBattStack->usDI3)
		{
			m_pBattStack->usEmerStopState = 1; //1 - 告警 
		}
		else
		{
			m_pBattStack->usEmerStopState = 2; //2 - 正常
		}
	}
    else if (113 == m_pBattStack->usEmerStopStrategy) //紧急停机 - 闭合告警
	{
		if (m_pBattStack->usDI3 > 0)
		{
			m_pBattStack->usEmerStopState = 1; //1 - 告警 
		}
		else
		{
			m_pBattStack->usEmerStopState = 2; //2 - 正常
		}
	}
	else if (104 == m_pBattStack->usEmerStopStrategy) //紧急停机 - 断开告警
	{
		if (0 == m_pBattStack->usDI4)
		{
			m_pBattStack->usEmerStopState = 1; //1 - 告警 
		}
		else
		{
			m_pBattStack->usEmerStopState = 2; //2 - 正常
		}
	}
    else if (114 == m_pBattStack->usEmerStopStrategy) //紧急停机 - 闭合告警
	{
		if (m_pBattStack->usDI4 > 0)
		{
			m_pBattStack->usEmerStopState = 1; //1 - 告警 
		}
		else
		{
			m_pBattStack->usEmerStopState = 2; //2 - 正常
		}
	}
	
	if (m_pBattStack->usLastEmerStopState != m_pBattStack->usEmerStopState) 
	{
		m_pBattStack->usLastEmerStopState = m_pBattStack->usEmerStopState;

		if (1 == m_pBattStack->usLastEmerStopState)
		{
			m_pBattStack->aEmerStop = 1;
		}
		else if (2 == m_pBattStack->usLastEmerStopState)
		{
			m_pBattStack->aEmerStop = 0;
		}
	}
}

void CDataTranSrv::checkEMSLink()
{
	if (0 == m_pBattStack->usEMSCommStrategy)
    {
        //EMS通讯策略(BMS界面可设置) 0-ModbusTCP 1-Xn104 2-Xn61850
		++m_iCheckEMSLinkCount;
		if (m_iCheckEMSLinkCount > 100)
		{
			m_iCheckEMSLinkCount = 300;
			if (0 == m_pBattStack->aEMSCommFault)
			{
				m_pBattStack->aEMSCommFault = 1;
			}
		}
		else
		{
			if (m_pBattStack->aEMSCommFault > 0)
			{
				m_pBattStack->aEMSCommFault = 0;
			}
		}
	}
}

int CDataTranSrv::GetBranNo(int iBankIndex)
{
    if (0 == m_pBattStack)
    {
        return 1;
    }

    int iAllBankNum = m_pBattStack->usInstallBankNum;
    int iBranBankNum = m_pBattStack->usMultiConfBankNum;
    int iBankNo = iBankIndex + 1;
    int iBranNo = qCeil(iBankNo/iBranBankNum); //当前簇属于哪个支路
    if (iBranNo < 1)
    {
        iBranNo = 1;
    }
    else if (iBranNo > iAllBankNum/iBranBankNum)
    {
        iBranNo = iAllBankNum/iBranBankNum;
    }

    return iBranNo;
}
